#1169 closed defect (invalid)
Last 11 Frames of H264 MOV Are Skipped When Decoding
Reported by: | mbradshaw | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avcodec |
Version: | git-master | Keywords: | |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
While working on a video reader I found I wasn't seeing all the frames from the video. It's possible I'm doing something wrong, but I haven't found any documentation that says I need to do anything special for decoding H264 video. The av_read_frame(formatContext, &packet)
returns nonzero 11 frames before the end of the video.
I transcoded the video with ffmpeg to mpeg2video, and the transcoded video did not show the same problem.
Minimal Reproducible Code Sample
#include <fstream> extern "C" { #include <avcodec.h> #include <avformat.h> #include <swscale.h> }; void saveFrame(const AVFrame* frame, int width, int height, int frameNumber) { char filename[32]; sprintf(filename, "frame%d.ppm", frameNumber); std::ofstream file(filename, std::ios_base::binary | std::ios_base::trunc | std::ios_base::out); if (!file.good()) { throw std::runtime_error("Unable to open the file to write the frame"); } file << "P5\n" << width << '\n' << height << "\n255\n"; for (int i = 0; i < height; ++i) { file.write((char*)(frame->data[0] + i * frame->linesize[0]), width); } } int main() { av_register_all(); AVFrame* frame = avcodec_alloc_frame(); if (!frame) { return 1; } AVFormatContext* formatContext = NULL; if (avformat_open_input(&formatContext, "in.mov", NULL, NULL) != 0) { av_free(frame); return 1; } if (avformat_find_stream_info(formatContext, NULL) < 0) { av_free(frame); av_close_input_file(formatContext); return 1; } if (formatContext->nb_streams < 1 || formatContext->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO) { av_free(frame); av_close_input_file(formatContext); return 1; } AVStream* stream = formatContext->streams[0]; AVCodecContext* codecContext = stream->codec; codecContext->codec = avcodec_find_decoder(codecContext->codec_id); if (codecContext->codec == NULL) { av_free(frame); avcodec_close(codecContext); av_close_input_file(formatContext); return 1; } else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) { av_free(frame); avcodec_close(codecContext); av_close_input_file(formatContext); return 1; } AVPacket packet; av_init_packet(&packet); std::ofstream stats("stats.txt"); int frameNumber = 0; while (av_read_frame(formatContext, &packet) == 0) { if (packet.stream_index == stream->index) { int frameFinished = 0; avcodec_decode_video2(codecContext, frame, &frameFinished, &packet); if (frameFinished) { saveFrame(frame, codecContext->width, codecContext->height, frameNumber++); stats << "repeat: " << frame->repeat_pict << "\tkeyframe: " << frame->key_frame << "\tbest_ts: " << frame->best_effort_timestamp << '\n'; } } } av_free_packet(&packet); av_free(frame); avcodec_close(codecContext); av_close_input_file(formatContext); }
Config options: ./configure --arch=x86 --enable-shared --disable-static
FFmpeg/libavcodec compiler: GCC/MinGW
Compiler for above sample: VC++ 2010
Expected output: frame0.ppm to frame 360.ppm
Actual output: frame0.ppm to frame 349.ppm
ffmpeg.exe -i in.mov
ffmpeg version 0.10.2.git-a45605a Copyright (c) 2000-2012 the FFmpeg developers built on Apr 4 2012 12:58:46 with gcc 4.6.1 configuration: --arch=x86 --enable-shared --disable-static libavutil 51. 44.100 / 51. 44.100 libavcodec 54. 12.100 / 54. 12.100 libavformat 54. 3.100 / 54. 3.100 libavdevice 53. 4.100 / 53. 4.100 libavfilter 2. 66.101 / 2. 66.101 libswscale 2. 1.100 / 2. 1.100 libswresample 0. 10.100 / 0. 10.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'in.mov': Metadata: major_brand : qt minor_version : 512 compatible_brands: qt encoder : Lavf54.3.100 Duration: 00:00:15.13, start: 0.000000, bitrate: 1002 kb/s Stream #0:0(eng): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 852x480 [SAR 1:1 DAR 71:40], 1000 kb/s, 23.92 fps, 24 tbr, 600 tbn, 47.95 tbc Metadata: handler_name : ♂DataHandler
Sample video attached.
Attachments (1)
Change History (5)
by , 13 years ago
comment:1 by , 13 years ago
Summary: | Last 11 Frames Are Skipped → Last 11 Frames of H264 MOV Are Skipped When Decoding |
---|
comment:2 by , 13 years ago
The sample contains 362 frames ("00:00:00:00" is repeated once and the last frame is "00:00:15:00"), ffmpeg decodes all of them (bitexact if compared with the reference decoder).
comment:3 by , 13 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Please read the documentation.
For example the one for avcodec_decode_video2 says:
- @note Codecs which have the CODEC_CAP_DELAY capability set have a delay
- between input and output, these need to be fed with avpkt->data=NULL,
- avpkt->size=0 at the end to return the remaining frames.
Since you are not doing that you do not have the chance of getting all frames decoded with most codecs.
Problematic video file