Revision: 32144 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32144 Author: schlaile Date: 2010-09-27 09:37:36 +0200 (Mon, 27 Sep 2010)
Log Message: ----------- Fix: [#24006] writeffmpeg doesn't flush delayed frames - fix attached and [#20843] FFmpeg H264 preset gives "Couldn't initialize codec" Thanks to Leo Sutic for the patch! Modified Paths: -------------- trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c Modified: trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c =================================================================== --- trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c 2010-09-27 07:01:08 UTC (rev 32143) +++ trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c 2010-09-27 07:37:36 UTC (rev 32144) @@ -160,7 +160,7 @@ pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - // XXX error("Error writing audio packet"); + fprintf(stderr, "Error writing audio packet!\n"); return -1; } return 0; @@ -290,7 +290,9 @@ packet.data = video_buffer; packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); - } else ret = 0; + } else { + ret = 0; + } if (ret != 0) { success= 0; @@ -778,6 +780,69 @@ return 1; } +/** + * Writes any delayed frames in the encoder. This function is called before + * closing the encoder. + * + * <p> + * Since an encoder may use both past and future frames to predict + * inter-frames (H.264 B-frames, for example), it can output the frames + * in a different order from the one it was given. + * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write + * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * and then the bidirectionally-predicted frames. What this means in practice + * is that the encoder may not immediately produce one output frame for each + * input frame. These delayed frames must be flushed before we close the + * stream. We do this by calling avcodec_encode_video with NULL for the last + * parameter. + * </p> + */ +void flush_ffmpeg(void) +{ + int outsize = 0; + int ret = 0; + + AVCodecContext* c = get_codec_from_stream(video_stream); + /* get the delayed frames */ + while (1) { + AVPacket packet; + av_init_packet(&packet); + + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL); + if (outsize < 0) { + fprintf(stderr, "Error encoding delayed frame %d\n", outsize); + break; + } + if (outsize == 0) { + break; + } + if (c->coded_frame->pts != AV_NOPTS_VALUE) { +#ifdef FFMPEG_CODEC_TIME_BASE + packet.pts = av_rescale_q(c->coded_frame->pts, + c->time_base, + video_stream->time_base); +#else + packet.pts = c->coded_frame->pts; +#endif + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + } else { + fprintf(stderr, "Video Frame PTS: not set\n"); + } + if (c->coded_frame->key_frame) { + packet.flags |= PKT_FLAG_KEY; + } + packet.stream_index = video_stream->index; + packet.data = video_buffer; + packet.size = outsize; + ret = av_interleaved_write_frame(outfile, &packet); + if (ret != 0) { + fprintf(stderr, "Error writing delayed frame %d\n", ret); + break; + } + } + avcodec_flush_buffers(get_codec_from_stream(video_stream)); +} + /* ********************************************************************** * public interface ********************************************************************** */ @@ -888,7 +953,6 @@ return success; } - void end_ffmpeg(void) { int i; @@ -905,6 +969,11 @@ audio_mixdown_device = 0; } + if (video_stream && get_codec_from_stream(video_stream)) { + fprintf(stderr, "Flushing delayed frames...\n"); + flush_ffmpeg (); + } + if (outfile) { av_write_trailer(outfile); } @@ -913,8 +982,8 @@ if (video_stream && get_codec_from_stream(video_stream)) { avcodec_close(get_codec_from_stream(video_stream)); + printf("zero video stream %p\n", video_stream); video_stream = 0; - printf("zero video stream %p\n", video_stream); } @@ -1195,20 +1264,47 @@ rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + /* + * All options here are for x264, but must be set via ffmpeg. + * The names are therefore different - Search for "x264 to FFmpeg option mapping" + * to get a list. + */ + + /* + * Use CABAC coder. Using "coder:1", which should be equivalent, + * crashes Blender for some reason. Either way - this is no big deal. + */ ffmpeg_property_add_string(rd, "video", "coder:vlc"); + + /* + * The other options were taken from the libx264-default.preset + * included in the ffmpeg distribution. + */ ffmpeg_property_add_string(rd, "video", "flags:loop"); ffmpeg_property_add_string(rd, "video", "cmp:chroma"); ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); ffmpeg_property_add_string(rd, "video", "me:hex"); - ffmpeg_property_add_string(rd, "video", "subq:5"); + ffmpeg_property_add_string(rd, "video", "subq:6"); ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "qdiff:4"); ffmpeg_property_add_string(rd, "video", "keyint_min:25"); ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); ffmpeg_property_add_string(rd, "video", "b_strategy:1"); - + ffmpeg_property_add_string(rd, "video", "bf:3"); + ffmpeg_property_add_string(rd, "video", "refs:2"); + ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); + ffmpeg_property_add_string(rd, "video", "directpred:3"); + ffmpeg_property_add_string(rd, "video", "trellis:0"); + ffmpeg_property_add_string(rd, "video", "flags2:wpred"); + ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); + ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); + ffmpeg_property_add_string(rd, "video", "wpredp:2"); + + // This makes x264 output lossless. Will be a separate option later. + //ffmpeg_property_add_string(rd, "video", "cqp:0"); break; case FFMPEG_PRESET_THEORA: _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs