Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Schlaile <peter@schlaile.de>2010-09-27 11:37:36 +0400
committerPeter Schlaile <peter@schlaile.de>2010-09-27 11:37:36 +0400
commit97cc369f72005d9a250abfc3d82ac1c559ca1393 (patch)
treeebb54b1ffbb6c773f0f9d0fe7f6549723cf9f608 /source/blender/blenkernel/intern/writeffmpeg.c
parentdbd5524970eddd4170d0b37461648523f4ce5cd9 (diff)
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!
Diffstat (limited to 'source/blender/blenkernel/intern/writeffmpeg.c')
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c108
1 files changed, 102 insertions, 6 deletions
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 6cd207f628c..473c10d6ced 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -160,7 +160,7 @@ static int write_audio_frame(void)
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 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports
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 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
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 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty,
return success;
}
-
void end_ffmpeg(void)
{
int i;
@@ -905,6 +969,11 @@ void end_ffmpeg(void)
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 @@ void end_ffmpeg(void)
if (video_stream && get_codec_from_stream(video_stream)) {
avcodec_close(get_codec_from_stream(video_stream));
- video_stream = 0;
printf("zero video stream %p\n", video_stream);
+ video_stream = 0;
}
@@ -1195,20 +1264,47 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
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: