Blender V2.61 - r43446
|
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 }