在标志中解码包含AV_PKT_FLAG_KEY的数据包之后,我期待获得I帧,但我获得了P帧:
致电后:
avcodec_decode_video2(codecCtx, frame, &frameFinished, &packet); // mpeg2 video
Run Code Online (Sandbox Code Playgroud)
我打印出以下内容作为完整性检查:
printf("packet flags: %d picture type: %c\n", packet.flags,
av_get_picture_type_char(frame->pict_type));
Run Code Online (Sandbox Code Playgroud)
返回输出:
packet flags: 1 picture type: P
Run Code Online (Sandbox Code Playgroud)
当我期待:
packet flags: 1 picture type: I
Run Code Online (Sandbox Code Playgroud)
'1'== AV_PKT_FLAG_KEY.和'我'指的是AV_PICTURE_TYPE_I,
这种行为是否正确?(我正在解码MPEG2视频).
我在这里问,如何将AVFrame转换为opengl纹理.实际上,我创建了一个渲染器,输出音频(音频正在工作)和视频,但视频没有输出.这是我的代码:
纹理创建:
glGenTextures(1,&_texture);
glBindTexture(GL_TEXTURE_2D,_texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
Run Code Online (Sandbox Code Playgroud)
代码信息:_texture变量是保持纹理ID的GLuint
获取AVFrame并将其转换为OpenGL纹理的函数:
int VideoGL::NextVideoFrame(){
// Get a packet from the queue
AVPacket *videopacket = this->DEQUEUE(VIDEO);
int frameFinished;
if(videopacket!=0){
avcodec_decode_video2(_codec_context_video, _std_frame,&frameFinished,videopacket);
if(frameFinished){
sws_scale(sws_ctx, _std_frame->data, _std_frame->linesize, 0, _codec_context_video->height, _rgb_frame->data, _rgb_frame->linesize);
if(_firstrendering){
glBindTexture(GL_TEXTURE_2D,_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _codec_context_video->width,_codec_context_video->height,0,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]);
_firstrendering = false;
}else{
glActiveTexture(_texture);
glBindTexture(GL_TEXTURE_2D,_texture);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_codec_context_video->width,_codec_context_video->height,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]);
}
av_free_packet(videopacket);
return 0;
}else{
av_free_packet(videopacket);
return -1;
}
}else{
return -1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码信息:有一个线程存储AVFrames的线程,这个函数经常被调用来获取AVFrame,直到它获得NULL它停止被调用.
这实际上不起作用.(我试着看看堆栈溢出中的一些问题,它仍然无法工作)任何一个例子,还是有人帮助我纠正那里的任何错误?
附加数据:我试图将GL_RGB更改为GL_RGBA并开始使用格式,无论如何当我尝试GL_RGBA时崩溃(因为宽度和高度非常大,无论如何我试图调整它们的大小).我试图将尺寸改为2的功率,仍然不起作用.
1编辑:
线程功能:
DWORD …Run Code Online (Sandbox Code Playgroud) 我正在使用FFMPEG进行C++音频流和回放应用.
我使用avformat_open_input函数打开外部压缩音频文件的URL,然后我逐步使用av_read_frame进行流式处理.然后,对于每个数据包,我直接解码数据并使用OpenAL将其排入音频缓冲区.
我的问题是FFMPEG内部是否从外部URL预先压缩了压缩数据?
即使我没有调用av_read_frame, FFMPEG是否会继续在后台下载数据?
或者我是否有责任维护一个中间缓冲区,我可以提前下载尽可能多的数据包以避免音频播放不足?
如果是这样,它内部缓冲/下载多少?我可以配置吗?
我一直在查看文档,但没有找到任何相关信息.
谢谢.
更新:根据这个帖子http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=376 libav默认情况下预缓冲大约5MB,具体取决于AVFormatContext :: max_analyze_duration.但是我没有注意到这种行为,如果我改变max_analyze_duration,它似乎没有改变.
如果我监视我的进程的内存消耗,它在调用avformat_open_input后不会增加,如果我模拟慢速网络,av_read_frame会直接停止工作,就像它没有缓冲任何数据包一样.
我正在研究一个libavformat API包装器,它将带有H.264和AAC的MP4文件转换为适合流式传输的MPEG-TS段.我只是在没有重新编码的情况下进行简单的流复制,但我生成的文件以3600 fps而不是24 fps 播放视频.
以下是ffprobe https://gist.github.com/chrisballinger/6733678的一些输出,损坏的文件如下:
r_frame_rate=1/1
avg_frame_rate=0/0
time_base=1/90000
start_pts=0
start_time=0.000000
duration_ts=2999
duration=0.033322
Run Code Online (Sandbox Code Playgroud)
通过ffmpeg手动发送的相同输入文件具有正确的时间戳信息:
r_frame_rate=24/1
avg_frame_rate=0/0
time_base=1/90000
start_pts=126000
start_time=1.400000
duration_ts=449850
duration=4.998333
Run Code Online (Sandbox Code Playgroud)
我认为这个问题存在于我的libavformat设置中:https://github.com/OpenWatch/FFmpegWrapper/blob/master/FFmpegWrapper/FFmpegWrapper.m#L349我在那里重新利用了ffmpeg.c中的一堆代码,这是必需的用于直接流复制.
由于3600看起来像一个"神奇的数字"(60*60),它可能就像我没有正确设置时间尺度一样简单,但我无法弄清楚我的代码与ffmpeg/avconv本身的分歧.
类似的问题在这里,但我认为他们没有达到我的目的:使用libavformat与vcopy/acopy混合使用H.264附件B和AAC流
我正在尝试使用FFMPEG和libavformat从WebM文件中检索持续时间和帧数.我正在调整一些最初编写的代码用于MP4s,并且当通过MP4时,它似乎工作正常.
我有使用vp8解析器和解码器以及matroska demuxer编译的FFMPEG 2.1.
我有一个AVStream指向视频流的指针*video_st.代码查找的帧数video_st->nb_frames和持续时间video_st->duration.这两者似乎都是0.
用于video_st->duration(https://ffmpeg.org/doxygen/trunk/structAVStream.html#a4e04af7a5a4d8298649850df798dd0b)的API文档说"如果源文件未指定持续时间,但指定比特率,则将根据比特率估计此值和文件大小." 我可以确认这个文件确实指定了持续时间和比特率(因为我在桌面上测试了它ffmpeg -i).所以这似乎很奇怪,这是返回0.也许我的FFMPEG构建配置不正确?
至于nb_frames,文档说"此流中的帧数(如果已知或0)".如果返回0,我能做什么吗?再次,ffmpeg -i确实返回fps的估计值; 这将足够好,因为我可以估计具有该帧数和持续时间的帧数.
谢谢!
目前,使用libavformat从代码生成碎片化MP4文件时遇到问题.我的文件可以使用VLC播放,但无法在(Chrome)浏览器中流式传输(通过WebSocket)和播放(通过MediaSource).(我用它来通过WebSocket测试流式分段MP4文件到浏览器).
注意:下面的文件由Baseline profile 4级编码.因此,您应该将MIME类型(在index.html中)更改为const mimeCodec ='video/mp4; 编解码器= "avc1.42C028"'; 能够发挥它们.
我检查并发现我生成的Mp4文件与使用ffmpeg工具生成的文件略有不同.
这就是我所做的:
我有一个.h264 文件
第一种方法,我使用ffmpeg生成碎片化的MP4文件.
ffmpeg -i temp.h264 -vcodec copy -f mp4 -movflags empty_moov+default_base_moof+frag_keyframe ffmpeg.mp4
Run Code Online (Sandbox Code Playgroud)
生成的文件可以由Quicktime播放器和VLC播放器播放
第二种方法,我使用libavformat以 programmaticaly方式生成碎片化的Mp4文件
首先我初始化上下文,codecin代码是AVCodecContext*输入流的
av_register_all();
avcodec_register_all();
int ret;
AVOutputFormat* fmt = av_guess_format("mp4", 0, 0);
if(!fmt) {
return;
}
AVFormatContext* ctx = avformat_alloc_context();
// Create AVIO context to capture generated Mp4 contain
uint8_t *avio_ctx_buffer = NULL;
size_t avio_ctx_buffer_size = 50000;
IOOutput buffer = {};
const …Run Code Online (Sandbox Code Playgroud)如何实现此命令的等效项:
ffmpeg -i test.h264 -vcodec copy -hls_time 5 -hls_list_size 0 foo.m3u8
Run Code Online (Sandbox Code Playgroud)
我的理解是您可以执行以下操作(为清楚起见,使用伪代码):
avformat_open_input(&ctx_in, "test.h264", NULL, NULL);
avformat_find_stream_info(ctx_in, NULL);
avformat_alloc_output_context2(&ctx_out, NULL, "hls", "foo.m3u8");
strm_out = avformat_new_stream(ctx_out, NULL);
strm_out->time_base = (AVRational){1000000, FRAMERATE};
strm_out->codecpar->codec_id = AV_CODEC_ID_H264;
strm_out->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
strm_out->codecpar->width = width;
strm_out->codecpar->height = height;
strm_out->codecpar->bit_rate = bitrate;
strm_out->codecpar->codec_tag = 0;
avcodec_parameters_copy(ctx_out->streams[0]->codecpar,
ctx_in->streams[0]->codecpar);
avformat_write_header(ctx_out, NULL);
while(1) {
AVPacket pkt;
ret = av_read_frame(ctx_in, &pkt);
if (ret < 0)
break;
pkt.pos = -1;
pkt.stream_index = 0;
pkt.dts = AV_NOPTS_VALUE;
pkt.pts = AV_NOPTS_VALUE;
pkt.pts = SOME_DURATION; …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用LibAV解码mpeg视频文件。我无法正确理解两个术语:Frames和Packets。
根据我目前的理解,帧是未压缩的视频帧,数据包是已压缩的帧。
问题:
我想要一个简单的工作示例,只使用libavformat来复用视频.有很好的例子(doc/examples/muxing.c)用libavcodec显示编码,用libavformat复用并用libavio保存数据.但是,我所知道的没有一个例子就是单独使用libavformat,在缓冲区中输入编码数据并在缓冲区中获取多路复用数据.
困难是双重的:一,添加流avformat_new_stream(AVFormatContext *s, const AVCodec *c)需要引用编解码器; 两个,多路复用的输出传递给AVFormatContext->pb它AVIOContext*.因此,似乎没有(明显的)方法从其他libav库中解放libavformat.
另请参阅:此问题提到了一种不使用libavio的方法:从libavformat获取TS数据包到缓冲区
我尝试使用 libavformat 创建.mp4具有单个 h.264 视频流的视频,但生成的文件中的最后一帧的持续时间通常为零,并且实际上从视频中删除。奇怪的是,最终帧是否被丢弃取决于我尝试添加到文件中的帧数。我在下面概述的一些简单测试让我认为我在某种程度上错误配置了AVFormatContexth.264 编码器,导致两个编辑列表有时会截断最终帧。我还将发布我正在使用的代码的简化版本,以防我犯一些明显的错误。任何帮助将不胜感激:过去几天我一直在努力解决这个问题,但进展甚微。
ffmpeg
如果我使用该选项,我可以通过使用带有复制编解码器的二进制文件创建一个新的 mp4 容器来恢复丢失的帧-ignore_editlist。ffprobe使用、mp4trackdump、 或来检查丢失帧的文件mp4file --dump表明,如果最终帧的采样时间与编辑列表末尾完全相同,则最终帧将被丢弃。当我制作一个没有丢帧的文件时,它仍然有两个编辑列表:唯一的区别是编辑列表的结束时间超出了没有丢帧的文件中的所有样本。虽然这不是一个公平的比较,但如果我.png为每个帧创建一个,然后使用编解码器和类似的 h.264 设置生成一个.mp4,ffmpeg我image2会制作一部包含所有帧的电影,只有一个编辑列表,以及与我的类似的 PTS 时间带有两个编辑列表的损坏的电影。在这种情况下,编辑列表始终在最后一帧/采样时间之后结束。
我使用此命令来确定结果流中的帧数,尽管我也通过其他实用程序获得相同的数字:
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 video_file_name.mp4
Run Code Online (Sandbox Code Playgroud)
使用 ffprobe 对文件进行简单检查,除了帧速率受到丢失帧的影响(目标为 24)之外,没有显示出明显令人担忧的迹象:
$ ffprobe -hide_banner testing.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testing.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.45.100
Duration: 00:00:04.13, start: 0.041016, bitrate: 724 kb/s …Run Code Online (Sandbox Code Playgroud) libavformat ×10
ffmpeg ×9
libav ×4
c++ ×3
h.264 ×3
libavcodec ×3
codec ×1
fmp4 ×1
media-source ×1
mp4 ×1
muxer ×1
opengl ×1
video ×1
webm ×1