Fix T38768: New "audio" button in 2.70 release does not 'mixdown' audio
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 28 Feb 2014 06:23:28 +0000 (12:23 +0600)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 28 Feb 2014 06:26:16 +0000 (12:26 +0600)
Issue was caused by the way how audio output works from audaspace.
Now made it much closer to what's happening in ffmpeg.c and writeffmpeg.c.

Also fixed issues with incompatible combinations of codecs and formats
in mixdown settings.

intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
source/blender/editors/sound/sound_ops.c

index d8f0d837fec01d91a690b6a5043491049f8c6eca..859227a500638bcfd3a72386db56fd073d89c62a 100644 (file)
@@ -187,14 +187,18 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
                        m_frame = av_frame_alloc();
                        if (!m_frame)
                                AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
+                       avcodec_get_frame_defaults(m_frame);
                        m_frame->linesize[0]    = m_input_size * samplesize;
                        m_frame->format         = m_codecCtx->sample_fmt;
+                       m_frame->nb_samples     = m_codecCtx->frame_size;
 #  ifdef FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
                        m_frame->sample_rate    = m_codecCtx->sample_rate;
 #  endif
 #  ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
                        m_frame->channel_layout = m_codecCtx->channel_layout;
 #  endif
+                       m_audio_sample_size = av_get_bytes_per_sample(m_codecCtx->sample_fmt);
+                       m_frame_pts = 0;
 #endif
 
                        try
@@ -272,13 +276,20 @@ void AUD_FFMPEGWriter::encode(sample_t* data)
 
 #ifdef FFMPEG_HAVE_ENCODE_AUDIO2
        int got_output, ret;
+       m_frame->pts = m_frame_pts / av_q2d(m_codecCtx->time_base);
+       m_frame_pts++;
+#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
+       m_frame->channel_layout = m_codecCtx->channel_layout;
+#endif
+
+       avcodec_fill_audio_frame(m_frame, m_codecCtx->channels, m_codecCtx->sample_fmt, reinterpret_cast<uint8_t*>(data),
+                                m_frame->nb_samples * av_get_bytes_per_sample(m_codecCtx->sample_fmt) * m_codecCtx->channels, 1);
 
-       m_frame->data[0] = reinterpret_cast<uint8_t*>(data);
        ret = avcodec_encode_audio2(m_codecCtx, &packet, m_frame, &got_output);
-       if (ret < 0)
+       if(ret < 0)
                AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
 
-       if (!got_output)
+       if(!got_output)
                return;
 #else
        sample_t* outbuf = m_output_buffer.getBuffer();
@@ -290,10 +301,23 @@ void AUD_FFMPEGWriter::encode(sample_t* data)
        packet.data = reinterpret_cast<uint8_t*>(outbuf);
 #endif
 
+       if(packet.pts != AV_NOPTS_VALUE)
+               packet.pts = av_rescale_q(packet.pts, m_codecCtx->time_base, m_stream->time_base);
+       if(packet.dts != AV_NOPTS_VALUE)
+               packet.dts = av_rescale_q(packet.dts, m_codecCtx->time_base, m_stream->time_base);
+       if(packet.duration > 0)
+               packet.duration = av_rescale_q(packet.duration, m_codecCtx->time_base, m_stream->time_base);
+
        packet.stream_index = m_stream->index;
 
-       if(av_interleaved_write_frame(m_formatCtx, &packet))
+       packet.flags |= AV_PKT_FLAG_KEY;
+
+       if(av_interleaved_write_frame(m_formatCtx, &packet)) {
+               av_free_packet(&packet);
                AUD_THROW(AUD_ERROR_FFMPEG, write_error);
+       }
+
+       av_free_packet(&packet);
 }
 
 void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer)
index 310f69258eaa2e963cc5c6efb27c08e76de6e81c..743d885fca8c837a5418f31ff7ffd88870e0b14f 100644 (file)
@@ -82,6 +82,16 @@ private:
         */
        AVFrame *m_frame;
 
+       /**
+        * PTS of next frame to write.
+        */
+       int m_frame_pts;
+
+       /**
+        * Number of bytes per sample.
+        */
+       int m_audio_sample_size;
+
        /**
         * The input buffer for the format converted data before encoding.
         */
index 168693db60baa827e0ccd4b59c1424f858cf3507..1979379032f856f47717eeb600ed20ffd902c573 100644 (file)
@@ -476,12 +476,6 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
                {0, NULL, 0, NULL, NULL}
        };
 
-       static EnumPropertyItem ac3_format_items[] = {
-               {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
-               {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
-               {0, NULL, 0, NULL, NULL}
-       };
-
 #ifdef WITH_SNDFILE
        static EnumPropertyItem flac_format_items[] = {
                {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
@@ -527,10 +521,9 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
 
        switch (container) {
                case AUD_CONTAINER_AC3:
-                       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
-                       RNA_def_property_enum_items(prop_format, ac3_format_items);
                        RNA_def_property_enum_items(prop_codec, all_codec_items);
                        RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
+                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
                        break;
                case AUD_CONTAINER_FLAC:
                        RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
@@ -539,9 +532,8 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
 #ifdef WITH_SNDFILE
                        RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
                        RNA_def_property_enum_items(prop_format, flac_format_items);
-#else
-                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
 #endif
+                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
                        break;
                case AUD_CONTAINER_MATROSKA:
                        RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
@@ -552,8 +544,7 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
                                        RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
                                        break;
                                case AUD_CODEC_AC3:
-                                       RNA_def_property_enum_items(prop_format, ac3_format_items);
-                                       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+                                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
                                        break;
                                case AUD_CODEC_FLAC:
                                        RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
@@ -565,6 +556,7 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
                                case AUD_CODEC_MP3:
                                        RNA_def_property_enum_items(prop_format, mp3_format_items);
                                        RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
+                                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
                                        break;
                                case AUD_CODEC_PCM:
                                        RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
@@ -589,11 +581,13 @@ static void sound_mixdown_draw(bContext *C, wmOperator *op)
                        RNA_def_property_enum_items(prop_format, mp3_format_items);
                        RNA_def_property_enum_items(prop_codec, all_codec_items);
                        RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
+                       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
                        break;
                case AUD_CONTAINER_OGG:
                        RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
                        RNA_def_property_enum_items(prop_codec, ogg_codec_items);
                        RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
+                       RNA_enum_set(op->ptr, "codec", AUD_CODEC_VORBIS);
                        break;
                case AUD_CONTAINER_WAV:
                        RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);