Blender V2.61 - r43446

AUD_FFMPEGWriter.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * Copyright 2009-2011 Jörg Hermann Müller
00005  *
00006  * This file is part of AudaSpace.
00007  *
00008  * Audaspace is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * AudaSpace is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Audaspace; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00030 // needed for INT64_C
00031 #ifndef __STDC_CONSTANT_MACROS
00032 #define __STDC_CONSTANT_MACROS
00033 #endif
00034 
00035 #include "AUD_FFMPEGWriter.h"
00036 
00037 extern "C" {
00038 #include <libavcodec/avcodec.h>
00039 #include <libavformat/avformat.h>
00040 #include <libavformat/avio.h>
00041 #include "ffmpeg_compat.h"
00042 }
00043 
00044 static const char* context_error = "AUD_FFMPEGWriter: Couldn't allocate context.";
00045 static const char* codec_error = "AUD_FFMPEGWriter: Invalid codec or codec not found.";
00046 static const char* stream_error = "AUD_FFMPEGWriter: Couldn't allocate stream.";
00047 static const char* format_error = "AUD_FFMPEGWriter: Unsupported sample format.";
00048 static const char* file_error = "AUD_FFMPEGWriter: File couldn't be written.";
00049 static const char* write_error = "AUD_FFMPEGWriter: Error writing packet.";
00050 
00051 AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) :
00052     m_position(0),
00053     m_specs(specs),
00054     m_input_samples(0)
00055 {
00056     static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" };
00057 
00058     if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str()))
00059         AUD_THROW(AUD_ERROR_FFMPEG, context_error);
00060 
00061     m_outputFmt = m_formatCtx->oformat;
00062 
00063     switch(codec)
00064     {
00065     case AUD_CODEC_AAC:
00066         m_outputFmt->audio_codec = CODEC_ID_AAC;
00067         break;
00068     case AUD_CODEC_AC3:
00069         m_outputFmt->audio_codec = CODEC_ID_AC3;
00070         break;
00071     case AUD_CODEC_FLAC:
00072         m_outputFmt->audio_codec = CODEC_ID_FLAC;
00073         break;
00074     case AUD_CODEC_MP2:
00075         m_outputFmt->audio_codec = CODEC_ID_MP2;
00076         break;
00077     case AUD_CODEC_MP3:
00078         m_outputFmt->audio_codec = CODEC_ID_MP3;
00079         break;
00080     case AUD_CODEC_PCM:
00081         switch(specs.format)
00082         {
00083         case AUD_FORMAT_U8:
00084             m_outputFmt->audio_codec = CODEC_ID_PCM_U8;
00085             break;
00086         case AUD_FORMAT_S16:
00087             m_outputFmt->audio_codec = CODEC_ID_PCM_S16LE;
00088             break;
00089         case AUD_FORMAT_S24:
00090             m_outputFmt->audio_codec = CODEC_ID_PCM_S24LE;
00091             break;
00092         case AUD_FORMAT_S32:
00093             m_outputFmt->audio_codec = CODEC_ID_PCM_S32LE;
00094             break;
00095         case AUD_FORMAT_FLOAT32:
00096             m_outputFmt->audio_codec = CODEC_ID_PCM_F32LE;
00097             break;
00098         case AUD_FORMAT_FLOAT64:
00099             m_outputFmt->audio_codec = CODEC_ID_PCM_F64LE;
00100             break;
00101         default:
00102             m_outputFmt->audio_codec = CODEC_ID_NONE;
00103             break;
00104         }
00105         break;
00106     case AUD_CODEC_VORBIS:
00107         m_outputFmt->audio_codec = CODEC_ID_VORBIS;
00108         break;
00109     default:
00110         m_outputFmt->audio_codec = CODEC_ID_NONE;
00111         break;
00112     }
00113 
00114     try
00115     {
00116         if(m_outputFmt->audio_codec == CODEC_ID_NONE)
00117             AUD_THROW(AUD_ERROR_SPECS, codec_error);
00118 
00119         m_stream = av_new_stream(m_formatCtx, 0);
00120         if(!m_stream)
00121             AUD_THROW(AUD_ERROR_FFMPEG, stream_error);
00122 
00123         m_codecCtx = m_stream->codec;
00124         m_codecCtx->codec_id = m_outputFmt->audio_codec;
00125         m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
00126         m_codecCtx->bit_rate = bitrate;
00127         m_codecCtx->sample_rate = int(m_specs.rate);
00128         m_codecCtx->channels = m_specs.channels;
00129         m_codecCtx->time_base.num = 1;
00130         m_codecCtx->time_base.den = m_codecCtx->sample_rate;
00131 
00132         switch(m_specs.format)
00133         {
00134         case AUD_FORMAT_U8:
00135             m_convert = AUD_convert_float_u8;
00136             m_codecCtx->sample_fmt = SAMPLE_FMT_U8;
00137             break;
00138         case AUD_FORMAT_S16:
00139             m_convert = AUD_convert_float_s16;
00140             m_codecCtx->sample_fmt = SAMPLE_FMT_S16;
00141             break;
00142         case AUD_FORMAT_S32:
00143             m_convert = AUD_convert_float_s32;
00144             m_codecCtx->sample_fmt = SAMPLE_FMT_S32;
00145             break;
00146         case AUD_FORMAT_FLOAT32:
00147             m_convert = AUD_convert_copy<float>;
00148             m_codecCtx->sample_fmt = SAMPLE_FMT_FLT;
00149             break;
00150         case AUD_FORMAT_FLOAT64:
00151             m_convert = AUD_convert_float_double;
00152             m_codecCtx->sample_fmt = SAMPLE_FMT_DBL;
00153             break;
00154         default:
00155             AUD_THROW(AUD_ERROR_FFMPEG, format_error);
00156         }
00157 
00158         try
00159         {
00160             if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
00161                 m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
00162 
00163             AVCodec* codec = avcodec_find_encoder(m_codecCtx->codec_id);
00164             if(!codec)
00165                 AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
00166 
00167             if(avcodec_open(m_codecCtx, codec))
00168                 AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
00169 
00170             m_output_buffer.resize(FF_MIN_BUFFER_SIZE);
00171             int samplesize = AUD_MAX(AUD_SAMPLE_SIZE(m_specs), AUD_DEVICE_SAMPLE_SIZE(m_specs));
00172 
00173             if(m_codecCtx->frame_size <= 1)
00174                 m_input_size = 0;
00175             else
00176             {
00177                 m_input_buffer.resize(m_codecCtx->frame_size * samplesize);
00178                 m_input_size = m_codecCtx->frame_size;
00179             }
00180 
00181             try
00182             {
00183                 if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE))
00184                     AUD_THROW(AUD_ERROR_FILE, file_error);
00185 
00186                 avformat_write_header(m_formatCtx, NULL);
00187             }
00188             catch(AUD_Exception&)
00189             {
00190                 avcodec_close(m_codecCtx);
00191                 av_freep(&m_formatCtx->streams[0]->codec);
00192                 throw;
00193             }
00194         }
00195         catch(AUD_Exception&)
00196         {
00197             av_freep(&m_formatCtx->streams[0]);
00198             throw;
00199         }
00200     }
00201     catch(AUD_Exception&)
00202     {
00203         av_free(m_formatCtx);
00204         throw;
00205     }
00206 }
00207 
00208 AUD_FFMPEGWriter::~AUD_FFMPEGWriter()
00209 {
00210     // writte missing data
00211     if(m_input_samples)
00212     {
00213         sample_t* buf = m_input_buffer.getBuffer();
00214         memset(buf + m_specs.channels * m_input_samples, 0,
00215                (m_input_size - m_input_samples) * AUD_DEVICE_SAMPLE_SIZE(m_specs));
00216 
00217         encode(buf);
00218     }
00219 
00220     av_write_trailer(m_formatCtx);
00221 
00222     avcodec_close(m_codecCtx);
00223 
00224     av_freep(&m_formatCtx->streams[0]->codec);
00225     av_freep(&m_formatCtx->streams[0]);
00226 
00227     avio_close(m_formatCtx->pb);
00228     av_free(m_formatCtx);
00229 }
00230 
00231 int AUD_FFMPEGWriter::getPosition() const
00232 {
00233     return m_position;
00234 }
00235 
00236 AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const
00237 {
00238     return m_specs;
00239 }
00240 
00241 void AUD_FFMPEGWriter::encode(sample_t* data)
00242 {
00243     sample_t* outbuf = m_output_buffer.getBuffer();
00244 
00245     // convert first
00246     if(m_input_size)
00247         m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels);
00248 
00249     AVPacket packet;
00250     av_init_packet(&packet);
00251     packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data));
00252     if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE)
00253         packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base);
00254     packet.flags |= AV_PKT_FLAG_KEY;
00255     packet.stream_index = m_stream->index;
00256     packet.data = reinterpret_cast<uint8_t*>(outbuf);
00257 
00258     if(av_interleaved_write_frame(m_formatCtx, &packet))
00259         AUD_THROW(AUD_ERROR_FFMPEG, write_error);
00260 }
00261 
00262 void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer)
00263 {
00264     unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
00265 
00266     if(m_input_size)
00267     {
00268         sample_t* inbuf = m_input_buffer.getBuffer();
00269 
00270         while(length)
00271         {
00272             unsigned int len = AUD_MIN(m_input_size - m_input_samples, length);
00273 
00274             memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize);
00275 
00276             buffer += len * m_specs.channels;
00277             m_input_samples += len;
00278             m_position += len;
00279             length -= len;
00280 
00281             if(m_input_samples == m_input_size)
00282             {
00283                 encode(inbuf);
00284 
00285                 m_input_samples = 0;
00286             }
00287         }
00288     }
00289     else // PCM data, can write directly!
00290     {
00291         int samplesize = AUD_SAMPLE_SIZE(m_specs);
00292         if(m_output_buffer.getSize() != length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8)
00293             m_output_buffer.resize(length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8);
00294         m_input_buffer.assureSize(length * AUD_MAX(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize));
00295 
00296         sample_t* buf = m_input_buffer.getBuffer();
00297         m_convert(reinterpret_cast<data_t*>(buf), reinterpret_cast<data_t*>(buffer), length * m_specs.channels);
00298 
00299         encode(buf);
00300 
00301         m_position += length;
00302     }
00303 }