audaspace: use new libavcodec audio encoding API where available
authorAnton Khirnov <anton@khirnov.net>
Sun, 26 Jan 2014 12:22:26 +0000 (13:22 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 28 Jan 2014 08:25:40 +0000 (14:25 +0600)
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
intern/ffmpeg/ffmpeg_compat.h

index d35b6d56c690706cc15a5b882ef16c69d83b7754..d8f0d837fec01d91a690b6a5043491049f8c6eca 100644 (file)
@@ -183,6 +183,20 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
                                m_input_size = m_codecCtx->frame_size;
                        }
 
+#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
+                       m_frame = av_frame_alloc();
+                       if (!m_frame)
+                               AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
+                       m_frame->linesize[0]    = m_input_size * samplesize;
+                       m_frame->format         = m_codecCtx->sample_fmt;
+#  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
+#endif
+
                        try
                        {
                                if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE))
@@ -229,6 +243,10 @@ AUD_FFMPEGWriter::~AUD_FFMPEGWriter()
        av_freep(&m_formatCtx->streams[0]->codec);
        av_freep(&m_formatCtx->streams[0]);
 
+#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
+       av_frame_free(&m_frame);
+#endif
+
        avio_close(m_formatCtx->pb);
        av_free(m_formatCtx);
 }
@@ -245,20 +263,34 @@ AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const
 
 void AUD_FFMPEGWriter::encode(sample_t* data)
 {
-       sample_t* outbuf = m_output_buffer.getBuffer();
-
        // convert first
        if(m_input_size)
                m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels);
 
-       AVPacket packet;
+       AVPacket packet = { 0 };
        av_init_packet(&packet);
+
+#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
+       int got_output, ret;
+
+       m_frame->data[0] = reinterpret_cast<uint8_t*>(data);
+       ret = avcodec_encode_audio2(m_codecCtx, &packet, m_frame, &got_output);
+       if (ret < 0)
+               AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
+
+       if (!got_output)
+               return;
+#else
+       sample_t* outbuf = m_output_buffer.getBuffer();
+
        packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data));
        if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE)
                packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base);
        packet.flags |= AV_PKT_FLAG_KEY;
-       packet.stream_index = m_stream->index;
        packet.data = reinterpret_cast<uint8_t*>(outbuf);
+#endif
+
+       packet.stream_index = m_stream->index;
 
        if(av_interleaved_write_frame(m_formatCtx, &packet))
                AUD_THROW(AUD_ERROR_FFMPEG, write_error);
index 17830308fd5726c1108379e8c895eab1b7efa85e..310f69258eaa2e963cc5c6efb27c08e76de6e81c 100644 (file)
@@ -77,6 +77,11 @@ private:
         */
        AVStream* m_stream;
 
+       /**
+        * Frame sent to the encoder.
+        */
+       AVFrame *m_frame;
+
        /**
         * The input buffer for the format converted data before encoding.
         */
index 91db329592dc18562223b32bad32474265ebc7d0..58cf62ab6236b6ce29c3fa1a2bf4979b98aad514 100644 (file)
 #define FFMPEG_HAVE_DECODE_AUDIO4
 #endif
 
+#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
+#define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
+#endif
+
 #if ((LIBAVUTIL_VERSION_MAJOR > 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 21))
 #define FFMPEG_FFV1_ALPHA_SUPPORTED
 #define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED
@@ -267,6 +271,10 @@ void avcodec_free_frame(AVFrame **frame)
 }
 #endif
 
+#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
+#define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
+#endif
+
 #if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13))
 #define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
 #endif
@@ -397,4 +405,18 @@ void avformat_close_input(AVFormatContext **ctx)
 }
 #endif
 
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0)
+FFMPEG_INLINE
+AVFrame *av_frame_alloc(void)
+{
+    return avcodec_alloc_frame();
+}
+
+FFMPEG_INLINE
+void av_frame_free(AVFrame **frame)
+{
+    av_freep(frame);
+}
+#endif
+
 #endif