2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #ifndef __STDC_CONSTANT_MACROS
22 #define __STDC_CONSTANT_MACROS
24 #ifndef __STDC_LIMIT_MACROS
25 #define __STDC_LIMIT_MACROS
30 #define INT64_C __int64
33 #include "EncoderFFmpeg.h"
34 #include "filesystem/File.h"
35 #include "utils/log.h"
36 #include "settings/Settings.h"
37 #include "utils/URIUtils.h"
39 /* AV_PKT_FLAG_KEY was named PKT_FLAG_KEY in older versions of libavcodec */
40 #ifndef AV_PKT_FLAG_KEY
41 #define AV_PKT_FLAG_KEY PKT_FLAG_KEY
44 CEncoderFFmpeg::CEncoderFFmpeg():
52 m_ResampledBuffer(NULL),
53 m_ResampledBufferSize(0),
54 m_ResampledFrame(NULL),
55 m_NeedConversion(false)
59 bool CEncoderFFmpeg::Init(const char* strFile, int iInChannels, int iInRate, int iInBits)
61 if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !m_dllSwResample.Load()) return false;
62 m_dllAvFormat.av_register_all();
63 m_dllAvCodec.avcodec_register_all();
65 CStdString filename = URIUtils::GetFileName(strFile);
66 if(m_dllAvFormat.avformat_alloc_output_context2(&m_Format,NULL,NULL,filename.c_str()))
68 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Unable to guess the output format for the file %s", filename.c_str());
73 codec = m_dllAvCodec.avcodec_find_encoder(m_Format->oformat->audio_codec);
77 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Unable to find a suitable FFmpeg encoder");
81 m_Format->pb = m_dllAvFormat.avio_alloc_context(m_BCBuffer, sizeof(m_BCBuffer), AVIO_FLAG_WRITE, this, NULL, avio_write_callback, avio_seek_callback);
84 m_dllAvUtil.av_freep(&m_Format);
85 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to allocate ByteIOContext");
89 m_Format->bit_rate = CSettings::Get().GetInt("audiocds.bitrate") * 1000;
91 /* add a stream to it */
92 m_Stream = m_dllAvFormat.avformat_new_stream(m_Format, codec);
95 m_dllAvUtil.av_freep(&m_Format->pb);
96 m_dllAvUtil.av_freep(&m_Format);
97 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to allocate AVStream context");
101 /* set the stream's parameters */
102 m_CodecCtx = m_Stream->codec;
103 m_CodecCtx->codec_id = codec->id;
104 m_CodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
105 m_CodecCtx->bit_rate = m_Format->bit_rate;
106 m_CodecCtx->sample_rate = iInRate;
107 m_CodecCtx->channels = iInChannels;
108 m_CodecCtx->channel_layout = m_dllAvUtil.av_get_default_channel_layout(iInChannels);
109 m_CodecCtx->time_base.num = 1;
110 m_CodecCtx->time_base.den = iInRate;
111 /* Allow experimental encoders (like FFmpeg builtin AAC encoder) */
112 m_CodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
114 if(m_Format->oformat->flags & AVFMT_GLOBALHEADER)
116 m_CodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
117 m_Format->flags |= CODEC_FLAG_GLOBAL_HEADER;
122 case 8: m_InFormat = AV_SAMPLE_FMT_U8 ; break;
123 case 16: m_InFormat = AV_SAMPLE_FMT_S16; break;
124 case 32: m_InFormat = AV_SAMPLE_FMT_S32; break;
126 m_dllAvUtil.av_freep(&m_Stream);
127 m_dllAvUtil.av_freep(&m_Format->pb);
128 m_dllAvUtil.av_freep(&m_Format);
132 m_OutFormat = codec->sample_fmts[0];
133 m_CodecCtx->sample_fmt = m_OutFormat;
135 m_NeedConversion = (m_OutFormat != m_InFormat);
137 if (m_OutFormat <= AV_SAMPLE_FMT_NONE || m_dllAvCodec.avcodec_open2(m_CodecCtx, codec, NULL))
139 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to open the codec %s", codec->long_name ? codec->long_name : codec->name);
140 m_dllAvUtil.av_freep(&m_Stream);
141 m_dllAvUtil.av_freep(&m_Format->pb);
142 m_dllAvUtil.av_freep(&m_Format);
146 /* calculate how many bytes we need per frame */
147 m_NeededFrames = m_CodecCtx->frame_size;
148 m_NeededBytes = m_dllAvUtil.av_samples_get_buffer_size(NULL, iInChannels, m_NeededFrames, m_InFormat, 0);
149 m_Buffer = (uint8_t*)m_dllAvUtil.av_malloc(m_NeededBytes);
152 m_BufferFrame = m_dllAvCodec.avcodec_alloc_frame();
153 if(!m_BufferFrame || !m_Buffer)
155 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to allocate necessary buffers");
156 if(m_BufferFrame) m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
157 if(m_Buffer) m_dllAvUtil.av_freep(&m_Buffer);
158 m_dllAvUtil.av_freep(&m_Stream);
159 m_dllAvUtil.av_freep(&m_Format->pb);
160 m_dllAvUtil.av_freep(&m_Format);
164 m_BufferFrame->nb_samples = m_CodecCtx->frame_size;
165 m_BufferFrame->format = m_InFormat;
166 m_BufferFrame->channel_layout = m_CodecCtx->channel_layout;
168 m_dllAvCodec.avcodec_fill_audio_frame(m_BufferFrame, iInChannels, m_InFormat, m_Buffer, m_NeededBytes, 0);
172 m_SwrCtx = m_dllSwResample.swr_alloc_set_opts(NULL,
173 m_CodecCtx->channel_layout, m_OutFormat, m_CodecCtx->sample_rate,
174 m_CodecCtx->channel_layout, m_InFormat, m_CodecCtx->sample_rate,
176 if(!m_SwrCtx || m_dllSwResample.swr_init(m_SwrCtx) < 0)
178 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to initialize the resampler");
179 m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
180 m_dllAvUtil.av_freep(&m_Buffer);
181 m_dllAvUtil.av_freep(&m_Stream);
182 m_dllAvUtil.av_freep(&m_Format->pb);
183 m_dllAvUtil.av_freep(&m_Format);
187 m_ResampledBufferSize = m_dllAvUtil.av_samples_get_buffer_size(NULL, iInChannels, m_NeededFrames, m_OutFormat, 0);
188 m_ResampledBuffer = (uint8_t*)m_dllAvUtil.av_malloc(m_ResampledBufferSize);
189 m_ResampledFrame = m_dllAvCodec.avcodec_alloc_frame();
190 if(!m_ResampledBuffer || !m_ResampledFrame)
192 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to allocate a frame for resampling");
193 if (m_ResampledFrame) m_dllAvCodec.avcodec_free_frame(&m_ResampledFrame);
194 if (m_ResampledBuffer) m_dllAvUtil.av_freep(&m_ResampledBuffer);
195 if (m_SwrCtx) m_dllSwResample.swr_free(&m_SwrCtx);
196 m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
197 m_dllAvUtil.av_freep(&m_Buffer);
198 m_dllAvUtil.av_freep(&m_Stream);
199 m_dllAvUtil.av_freep(&m_Format->pb);
200 m_dllAvUtil.av_freep(&m_Format);
203 m_ResampledFrame->nb_samples = m_NeededFrames;
204 m_ResampledFrame->format = m_OutFormat;
205 m_ResampledFrame->channel_layout = m_CodecCtx->channel_layout;
206 m_dllAvCodec.avcodec_fill_audio_frame(m_ResampledFrame, iInChannels, m_OutFormat, m_ResampledBuffer, m_ResampledBufferSize, 0);
209 /* set input stream information and open the file */
210 if (!CEncoder::Init(strFile, iInChannels, iInRate, iInBits))
212 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to call CEncoder::Init");
213 if (m_ResampledFrame ) m_dllAvCodec.avcodec_free_frame(&m_ResampledFrame);
214 if (m_ResampledBuffer) m_dllAvUtil.av_freep(&m_ResampledBuffer);
215 if (m_SwrCtx) m_dllSwResample.swr_free(&m_SwrCtx);
216 m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
217 m_dllAvUtil.av_freep(&m_Buffer);
218 m_dllAvUtil.av_freep(&m_Stream);
219 m_dllAvUtil.av_freep(&m_Format->pb);
220 m_dllAvUtil.av_freep(&m_Format);
225 SetTag("album" , m_strAlbum);
226 SetTag("album_artist", m_strArtist);
227 SetTag("genre" , m_strGenre);
228 SetTag("title" , m_strTitle);
229 SetTag("track" , m_strTrack);
230 SetTag("encoder" , "XBMC FFmpeg Encoder");
232 /* write the header */
233 if (m_dllAvFormat.avformat_write_header(m_Format, NULL) != 0)
235 CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to write the header");
236 if (m_ResampledFrame ) m_dllAvCodec.avcodec_free_frame(&m_ResampledFrame);
237 if (m_ResampledBuffer) m_dllAvUtil.av_freep(&m_ResampledBuffer);
238 if (m_SwrCtx) m_dllSwResample.swr_free(&m_SwrCtx);
239 m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
240 m_dllAvUtil.av_freep(&m_Buffer);
241 m_dllAvUtil.av_freep(&m_Stream);
242 m_dllAvUtil.av_freep(&m_Format->pb);
243 m_dllAvUtil.av_freep(&m_Format);
247 CLog::Log(LOGDEBUG, "CEncoderFFmpeg::Init - Successfully initialized with muxer %s and codec %s", m_Format->oformat->long_name? m_Format->oformat->long_name : m_Format->oformat->name, codec->long_name? codec->long_name : codec->name);
252 void CEncoderFFmpeg::SetTag(const CStdString tag, const CStdString value)
254 m_dllAvUtil.av_dict_set(&m_Format->metadata, tag.c_str(), value.c_str(), 0);
257 int CEncoderFFmpeg::avio_write_callback(void *opaque, uint8_t *buf, int buf_size)
259 CEncoderFFmpeg *enc = (CEncoderFFmpeg*)opaque;
260 if(enc->FileWrite(buf, buf_size) != buf_size)
262 CLog::Log(LOGERROR, "Error writing FFmpeg buffer to file");
268 int64_t CEncoderFFmpeg::avio_seek_callback(void *opaque, int64_t offset, int whence)
270 CEncoderFFmpeg *enc = (CEncoderFFmpeg*)opaque;
271 return enc->FileSeek(offset, whence);
274 int CEncoderFFmpeg::Encode(int nNumBytesRead, BYTE* pbtStream)
276 while(nNumBytesRead > 0)
278 unsigned int space = m_NeededBytes - m_BufferSize;
279 unsigned int copy = (unsigned int)nNumBytesRead > space ? space : nNumBytesRead;
281 memcpy(&m_Buffer[m_BufferSize], pbtStream, copy);
282 m_BufferSize += copy;
284 nNumBytesRead -= copy;
286 /* only write full packets */
287 if (m_BufferSize == m_NeededBytes)
288 if (!WriteFrame()) return 0;
294 bool CEncoderFFmpeg::WriteFrame()
296 int encoded, got_output;
299 m_dllAvCodec.av_init_packet(&m_Pkt);
305 if (m_dllSwResample.swr_convert(m_SwrCtx, m_ResampledFrame->extended_data, m_NeededFrames, (const uint8_t**)m_BufferFrame->extended_data, m_NeededFrames) < 0)
307 CLog::Log(LOGERROR, "CEncoderFFmpeg::WriteFrame - Error resampling audio");
310 frame = m_ResampledFrame;
312 else frame = m_BufferFrame;
314 encoded = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
319 CLog::Log(LOGERROR, "CEncoderFFmpeg::WriteFrame - Error encoding audio: %i", encoded);
325 if (m_CodecCtx->coded_frame && m_CodecCtx->coded_frame->pts != AV_NOPTS_VALUE)
326 m_Pkt.pts = m_dllAvUtil.av_rescale_q(m_CodecCtx->coded_frame->pts, m_Stream->time_base, m_CodecCtx->time_base);
328 if (m_dllAvFormat.av_write_frame(m_Format, &m_Pkt) < 0) {
329 CLog::Log(LOGERROR, "CEncoderFFMmpeg::WriteFrame - Failed to write the frame data");
334 m_dllAvCodec.av_free_packet(&m_Pkt);
339 bool CEncoderFFmpeg::Close()
342 /* if there is anything still in the buffer */
343 if (m_BufferSize > 0) {
344 /* zero the unused space so we dont encode random junk */
345 memset(&m_Buffer[m_BufferSize], 0, m_NeededBytes - m_BufferSize);
346 /* write any remaining data */
350 /* Flush if needed */
351 m_dllAvUtil.av_freep(&m_Buffer);
352 m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
354 if (m_SwrCtx) m_dllSwResample.swr_free(&m_SwrCtx);
355 if (m_ResampledFrame ) m_dllAvCodec.avcodec_free_frame(&m_ResampledFrame);
356 if (m_ResampledBuffer) m_dllAvUtil.av_freep(&m_ResampledBuffer);
357 m_NeedConversion = false;
361 /* write the trailer */
362 m_dllAvFormat.av_write_trailer(m_Format);
367 m_dllAvCodec.avcodec_close(m_CodecCtx);
368 m_dllAvUtil.av_freep(&m_Stream );
369 m_dllAvUtil.av_freep(&m_Format->pb);
370 m_dllAvUtil.av_freep(&m_Format );
375 m_dllAvFormat.Unload();
376 m_dllAvUtil .Unload();
377 m_dllAvCodec .Unload();
378 m_dllSwResample.Unload();