从avi转换为mp4(x264)时,我遇到了fps问题.最终问题出现在PTS和DTS值中,因此第12-15行在av_interleaved_write_frame函数之前添加:
1. AVFormatContext* outContainer = NULL;
2. avformat_alloc_output_context2(&outContainer, NULL, "mp4", "c:\\test.mp4";
3. AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
4. AVStream *outStream = avformat_new_stream(outContainer, encoder);
5. // outStream->codec initiation
6. // ...
7. avformat_write_header(outContainer, NULL);
8. // reading and decoding packet
9. // ...
10. avcodec_encode_video2(outStream->codec, &encodedPacket, decodedFrame, &got_frame)
11.
12. if (encodedPacket.pts != AV_NOPTS_VALUE)
13. encodedPacket.pts = av_rescale_q(encodedPacket.pts, outStream->codec->time_base, outStream->time_base);
14. if (encodedPacket.dts != AV_NOPTS_VALUE)
15. encodedPacket.dts = av_rescale_q(encodedPacket.dts, outStream->codec->time_base, outStream->time_base);
16.
17. av_interleaved_write_frame(outContainer, &encodedPacket)
Run Code Online (Sandbox Code Playgroud)
看完很多帖后我还是不明白:
outStream->codec->time_base= 1/25和outStream->time_base= 1/12800.第一个由我设定,但我无法弄清楚为什么和谁设置12800?我注意到在行(7) …如何在FFmpeg C API编码之前计算帧的正确PTS值?
对于编码我正在使用函数avcodec_encode_video2,然后通过编写它av_interleaved_write_frame.
我发现了一些公式,但其中没有一个不起作用.
在doxygen示例中,他们正在使用
frame->pts = 0;
for (;;) {
// encode & write frame
// ...
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
Run Code Online (Sandbox Code Playgroud)
这篇博客说公式必须是这样的:
(1/FPS)*采样率*帧数
有人只使用帧号来设置pts:
frame->pts = videoCodecCtx->frame_number;
Run Code Online (Sandbox Code Playgroud)
或者替代方式:
int64_t now = av_gettime();
frame->pts = av_rescale_q(now, (AVRational){1, 1000000}, videoCodecCtx->time_base);
Run Code Online (Sandbox Code Playgroud)
最后一个:
// 40 * 90 means 40 ms and 90 because of the 90kHz by the standard for PTS-values.
frame->pts = encodedFrames * 40 * 90;
Run Code Online (Sandbox Code Playgroud)
哪一个是正确的?我认为这个问题的答案不仅对我有帮助.
同步一直让我着迷,或者更确切地说:为什么媒体播放器可以同步查看.ts,而重新组合的多路分解音频+视频不同步.
所以我试图理解这一点,以及可以做些什么来防止它.
我已经阅读了以下内容:https: //trac.handbrake.fr/wiki/LibHandBrakeSync和sync.c的源代码(也可以在wiki上找到)
BitStreamTools也写了关于这个主题的理论101(但我无法链接,因为我是新用户,抱歉)
虽然我认为我对PCR/PTS的理解是(概念上)正确的,但我很难跟上手刹的优秀A/V同步纸.
我的问题是:是否有一些直观的(可能是简短的,短的或更长的,同样长的)a/v同步的解释?虽然我知道如果音频或视频pts被破坏(不连续?),可以从PCR重新计算PTS,手刹似乎不依赖于此,而是依赖于它的内部PTS.0,+ = 1/fps(〜= 5),10,15,....
是否有可能通过修复所有音频和视频PTS值来重新计算pts偏移并校正.ts(二进制)(并且使用相同的偏移量倾斜所有DTS,因此播放器不会"耗尽帧",所以因此,有一个可以被解复用的.ts,然后隔离的轨道同步(如果放回去)?
编辑:或者不可能通过使用PCR来重新计算给定.ts中的所有PTS值?虽然我知道有些帧/音频可能在广播中被损坏而无法正确显示,但我会留下处理(如删除视频,如果它被损坏并有相应的音频部分,插入x ms静音,如果音频包被损坏等等以后,为了讨论起见,我假设所有帧都完好无损.(但那么PTS值总是正确的,或者是什么?)
附录:我对手刹A/V纸的看法是:在"预期"100处,偏移量计算为视频点(100) - 音频点(0) - 内部PTS,将音频带到同一个演示文稿时间,因此给出了99的偏移量.在105处,偏移量将是105-5 = 100,而不是99,但我们继续使用99作为偏移量,因为不需要重新计算(100-99 = 1.1/fps < 100毫秒).在150处,随着视频点的减少,再次计算pts偏移,而不是增加...
我几乎是肯定的,我对此完全错了,但是有人能指出我正确的方向吗?
我有一个使用STDIN 3(/proc/xxxx/fd/0 -> /dev/pts/3)的终端
所以如果(在另一个终端)我这样做:
echo 'do_something_command' > /dev/pts/3
Run Code Online (Sandbox Code Playgroud)
该命令显示在我的first(pts/3)终端中,但该命令未执行.如果(在这个终端中pts/3)我在一个等待来自某个数据的程序中stdin,数据会写在屏幕上,但程序不能从中捕获数据stdin.
我想要做的是执行命令"do_something_command",而不仅仅是显示它.
有人可以向我解释这种行为吗?我如何实现我的意图?
我正在使用一个使用IBBP ... GOP序列的mpeg流.(DTS,PTS)前4个AVPackets返回的值如下:I=(0,3) B=(1,1) B=(2,2) P=(3,6)
I帧上的PTS看起来是合法的,但是B帧上的PTS不能正确,因为B帧不应该在I帧之前显示,因为它们的PTS值表示.我也尝试解码数据包并在生成的AVFrame中使用pts值,将PTS始终设置为零.
有没有办法从ffmpeg中获得准确的PTS?如果没有,那么同步音频的最佳方式是什么呢?
我正在运行 qemu
-串行 pty
选项,qemu 给出了这个消息
字符设备重定向到/dev/pts/1
但是,它不会生成新窗口,我可以cat从不同的窗口对 pts1 执行操作,但随后我无法向其中输入任何字符。
无论如何,你可以启动一个具有特定点数的新 xterm 吗?
我想编写一个在串口上模拟设备的程序.我正在尝试使用伪终端来实现这一目标.我想要一个独特的过程来控制主人.此过程充当串行设备模拟器.我希望另一个进程(例如kermit)能够使用从终端与主站通信.由于不同的工艺要求,我没有使用任何叉子.几乎互联网上的每个伪终端示例都显示了fork()用于主/从.
我让它在一个方向上工作.也就是说,我可以让从属进程将数据写入从属伪终端,并且主机将从主假终端读取它就好了.
问题出在另一个方向.我无法让master写入数据和slave来读取数据.
我将展示非工作双向代码和工作单向代码.
非工作双向主控:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
// get the master fd
int masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if(masterfd < 0)
{
perror("getpt");
exit(1);
}
// grant access to the slave
if(grantpt(masterfd) < 0)
{
perror("grantpt");
exit(1);
}
// unlock the slave
if(unlockpt(masterfd) < 0)
{
perror("unlockpt");
exit(1);
}
// get the path to the slave
char slavepath[64];
if(ptsname_r(masterfd, slavepath, sizeof(slavepath)) < 0)
{
perror("ptsname_r");
exit(1);
} …Run Code Online (Sandbox Code Playgroud) 我正在一个小型图书馆上创建一对相互关联的pts。我使用epoll fd,在其中master fd为EPOLLIN事件的两个伪终端注册。当我的示例客户端程序启动时,事件循环处于空闲状态,因此两个客户端(在我的情况下为microcom)打开每个从属设备。但是,当任何一个客户端关闭它的从属端时,它将epoll_wait连续报告EPOLLHUP该从属主机的事件。
为了防止这种情况,我O_WRONLY在每个从属服务器上都打开了一个文件描述符,它可以工作(不再可用EPOLLHUP),但是我认为这不是真正的解决方案,而是更多的黑客手段。在这个情况下。
我试图:
EPOLL_CTL_DEL 然后重新添加制作HUP的主文件这些尝试均未显示任何结果。
在发生EPOLLHUP之后,是否可以清理“ HUP状态”并将主文件描述符恢复为从属文件打开之前的状态?
我正在使用 Wireshark 来检查数据包,但我对 RTMP 流媒体中如何遵循 flv 格式感到困惑。FLV 文档指定标签为:标签类型、数据大小、时间戳、时间戳扩展、streamID、VideoTagHeader,但我得到
[fmt] [timestamp 2000] [body size], [typeID (tag type)] [stream ID]
04 00 07 d0 00 00 2c 09 01 00 00 00
Run Code Online (Sandbox Code Playgroud)
流媒体时,FLV时间戳是否只使用RTMP时间戳?因此不遵循大端格式而是使用 RTMP 扩展时间戳?
那么FLV容器到底是如何在RTMP视频流中使用的呢?