使用libav转码视频时发现一个问题:使用下面这段代码解码视频时,视频尾巴上会丢掉几帧。
while(av_read_frame(ifmt_ctx,&packet) >= 0){ ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } }
这是因为源视频中PTS与DTS的不同造成的。
av_read_frame()按照PTS顺序读帧的时候,如果此帧需要参考后面的帧,那么此时avcodec_decode_video2()是没有能力解码此帧的,表现为got_frame返回0。
比如说遇上如下EFGH四帧:
ID :E F G H
KIND:I B P P
PTS : 1 2 3 4
DTS : 1 4 2 3
那么顺序读到F时,由于F需要参考G帧,而此时我们还没读到G帧,我们是没有解码F的能力的,got_frame就返回0了。如果我们对此事不做处理,那么我们就会丢掉一个帧(但丢掉的未必是F,因为av_read_frame()和avcodec_decode_video2()是1:1调用的)。
所以我们需要在while(av_read_frame())读完整个视频后,继续调用avcodec_decode_video2()把之前那些没有成功解码的帧都解出来。调用的次数就是之前got_frame返回0的次数。
按照上述思路变更代码为以下,成功找回丢失的帧。
int skipped_frame = 0; while(av_read_frame(ifmt_ctx,&packet) >= 0){ ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } else { skipped_frame++; } } for(int i=skipped_frame; i>0; i--) { ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } }
相关推荐
5. **读取/写入数据**:在解码过程中,使用`av_read_frame`从输入文件中读取一帧数据,然后调用`avcodec_decode_video2`或`avcodec_decode_audio4`进行解码。在编码过程中,将原始数据送入`avcodec_encode_video2`或...
- 解码后的帧通过 `avcodec_encode_video2` 使用编码器编码为新的格式,最后 `av_interleaved_write_frame` 将编码后的数据写入输出文件。 3. **视频截图**: - 截图功能主要涉及解码视频帧。可以使用 `av_read_...
1. **旧API**:使用`avcodec_decode_video2`进行解码,需要先发送编码数据包到解码器,然后通过此函数接收解码后的AVFrame。解码后的AVFrame包含了视频帧的数据,可以是YUV、RGB等格式。 2. **新API**:在新API中,...
使用FFmpeg API可以简化多媒体处理的复杂性,比如使用`avcodec_decode_video2()`解码H264数据,`avcodec_encode_audio2()`编码PCM数据,`avformat_write_header()`和`av_interleaved_write_frame()`写入FLV容器。...
在你的Win32Project1工程中,你需要找到视频解码的部分,通常是通过调用`avcodec_open2()`函数初始化解码器,并使用`avcodec_decode_video2()`函数进行解码。为了启用DXVA2硬件加速,你需要在调用`avcodec_open2()`...
然后调用`avcodec_decode_video2`函数进行解码,此函数会返回解码后的数据是否成功。如果成功,`pFrame`参数会指向解码出的AVFrame结构体,包含了解码后的像素数据。 解码后的每一帧可能包括多个颜色平面(如YUV420...
调用`avcodec_open2()`初始化解码器,之后可以使用`avcodec_decode_video2()`对解码后的像素数据进行解包。 3. **Encoding(编码)**:如果需要重新编码,过程与解码类似,但这里使用的是编码器。`avcodec_find_...
一旦准备就绪,可以使用`avcodec_decode_video2()`或`avcodec_decode_audio4()`函数进行实际的解码操作,将字节流解码为`AVFrame`结构,其中包含了视频帧的数据。 逐帧编码,顾名思义,是指对视频的每一帧进行独立...
例如,我们可以使用avcodec_decode_video()函数来解码视频帧,并使用av_read_frame()函数来读取音频帧。 FFmpeg提供了一个强大的解决方案来实现音视频同步。在Android客户端中,我们可以使用FFmpeg来实现音视频同步...
接着,使用 `avcodec_decode_video2()` 函数解码 NAL 单元,获取到解码后的 YUV 帧。解码完成后,关闭解码器。 在 `FFMPEG_apiexample.c` 示例中,源代码可能保持了 FFmpeg API 的基本结构,没有进行大规模修改,...
接着,使用`avcodec_decode_video2`解码每一帧数据。 4. 图像渲染:解码后的数据是YUV格式,可以使用OpenGL ES或Metal进行渲染。 四、音频解码 1. 类似视频解码,首先找到音频流,然后获取解码器。 2. 创建解码器上...
4. 解码NAL单元:调用`avcodec_decode_video2()`或`avcodec_send_packet()`和`avcodec_receive_frame()`这两个函数交替进行,将NAL单元送入解码器并接收解码后的帧。 5. 处理解码结果:解码成功后,`AVFrame`结构体...
在循环中,调用av_read_frame()读取一帧数据,avcodec_decode_video2()解码视频帧,然后显示到屏幕上。 4. 解码与渲染:FFmpeg的avcodec_decode_video2()函数将编码后的数据解码为原始像素数据。解码后的帧可能是...
在使用avcodec-58.dll时,开发者需要熟悉FFmpeg的API接口,如avcodec_find_decoder()来寻找解码器,avcodec_open2()来初始化解码器,并通过avcodec_decode_video2()或avcodec_decode_audio4()进行解码操作。...
这通常通过读取AVPacket(封装了音视频数据的结构体)并调用`avcodec_decode_video2()`函数实现。 ```c++ AVPacket pkt; av_init_packet(&pkt); while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_...
5. **解码数据**:循环读取输入流的packet(`av_read_frame()`),然后使用`avcodec_decode_video2()`或`avcodec_decode_audio4()`进行解码。 6. **处理解码后的数据**:解码成功后,会返回解码后的AVFrame,从中...
- avcodec_decode_audio4或avcodec_decode_video2:对数据包进行解码。 - av_frame_free:释放不再需要的AVFrame资源。 4. **教程04.c**: - 音视频帧处理:讲解如何处理解码后的音视频帧,包括显示、播放或...
解码过程由`avcodec_decode_video2()`函数完成,它会将编码的视频帧解码成AVFrame结构体。需要注意的是,解码并不总是成功,因此需要检查返回值并处理解码错误。 解码后的AVFrame包含了原始的像素数据,可以进一步...
解码过程由`avcodec_decode_video2`或`avcodec_send_packet/avcodec_receive_frame`完成。前者是旧版接口,后者是新版本的异步解码方式。在解码过程中,需要不断向解码器发送编码的`AVPacket`,并接收解码后的`...
4. 解码关键帧:使用`avcodec_decode_video2`进行解码,得到解码后的像素数据。 5. 渲染或保存:根据需求,可以将解码后的关键帧显示在屏幕上或者保存为图片文件。 6. 清理:使用`avcodec_close`关闭解码器,`...