Merge pull request #2948 from ace20022/blu_lang_fix
[vuplus_xbmc] / xbmc / cdrip / EncoderFFmpeg.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #ifndef __STDC_CONSTANT_MACROS
22 #define __STDC_CONSTANT_MACROS
23 #endif
24 #ifndef __STDC_LIMIT_MACROS
25 #define __STDC_LIMIT_MACROS
26 #endif
27 #ifdef TARGET_POSIX
28 #include "stdint.h"
29 #else
30 #define INT64_C __int64
31 #endif
32
33 #include "EncoderFFmpeg.h"
34 #include "filesystem/File.h"
35 #include "utils/log.h"
36 #include "settings/Settings.h"
37 #include "utils/URIUtils.h"
38
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
42 #endif
43
44 CEncoderFFmpeg::CEncoderFFmpeg():
45   m_Format    (NULL),
46   m_CodecCtx  (NULL),
47   m_SwrCtx    (NULL),
48   m_Stream    (NULL),
49   m_Buffer    (NULL),
50   m_BufferSize(0),
51   m_BufferFrame(NULL),
52   m_ResampledBuffer(NULL),
53   m_ResampledBufferSize(0),
54   m_ResampledFrame(NULL),
55   m_NeedConversion(false)
56 {
57 }
58
59 bool CEncoderFFmpeg::Init(const char* strFile, int iInChannels, int iInRate, int iInBits)
60 {
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();
64
65   CStdString filename = URIUtils::GetFileName(strFile);
66   if(m_dllAvFormat.avformat_alloc_output_context2(&m_Format,NULL,NULL,filename.c_str()))
67   {
68     CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Unable to guess the output format for the file %s", filename.c_str());
69     return false;
70   }
71
72   AVCodec *codec;
73   codec = m_dllAvCodec.avcodec_find_encoder(m_Format->oformat->audio_codec);
74
75   if (!codec)
76   {
77     CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Unable to find a suitable FFmpeg encoder");
78     return false;
79   }
80
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);
82   if (!m_Format->pb)
83   {
84     m_dllAvUtil.av_freep(&m_Format);
85     CLog::Log(LOGERROR, "CEncoderFFmpeg::Init - Failed to allocate ByteIOContext");
86     return false;
87   }
88
89   m_Format->bit_rate = CSettings::Get().GetInt("audiocds.bitrate") * 1000;
90
91   /* add a stream to it */
92   m_Stream = m_dllAvFormat.avformat_new_stream(m_Format, codec);
93   if (!m_Stream)
94   {
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");
98     return false;
99   }
100
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;
113
114   if(m_Format->oformat->flags & AVFMT_GLOBALHEADER)
115   {
116     m_CodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
117     m_Format->flags   |= CODEC_FLAG_GLOBAL_HEADER;
118   }
119
120   switch(iInBits)
121   {
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;
125     default:
126       m_dllAvUtil.av_freep(&m_Stream);
127       m_dllAvUtil.av_freep(&m_Format->pb);
128       m_dllAvUtil.av_freep(&m_Format);
129       return false;
130   }
131
132   m_OutFormat = codec->sample_fmts[0];
133   m_CodecCtx->sample_fmt = m_OutFormat;
134
135   m_NeedConversion = (m_OutFormat != m_InFormat);
136
137   if (m_OutFormat <= AV_SAMPLE_FMT_NONE || m_dllAvCodec.avcodec_open2(m_CodecCtx, codec, NULL))
138   {
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);
143     return false;
144   }
145
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);
150   m_BufferSize   = 0;
151
152   m_BufferFrame = m_dllAvCodec.avcodec_alloc_frame();
153   if(!m_BufferFrame || !m_Buffer)
154   {
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);
161     return false;
162   }
163
164   m_BufferFrame->nb_samples     = m_CodecCtx->frame_size;
165   m_BufferFrame->format         = m_InFormat;
166   m_BufferFrame->channel_layout = m_CodecCtx->channel_layout;
167
168   m_dllAvCodec.avcodec_fill_audio_frame(m_BufferFrame, iInChannels, m_InFormat, m_Buffer, m_NeededBytes, 0);
169
170   if(m_NeedConversion)
171   {
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,
175                     0, NULL);
176     if(!m_SwrCtx || m_dllSwResample.swr_init(m_SwrCtx) < 0)
177     {
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);
184       return false;
185     }
186
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)
191     {
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);
201       return false;
202     }
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);
207   }
208
209   /* set input stream information and open the file */
210   if (!CEncoder::Init(strFile, iInChannels, iInRate, iInBits))
211   {
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);
221     return false;
222   }
223
224   /* set the tags */
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");
231
232   /* write the header */
233   if (m_dllAvFormat.avformat_write_header(m_Format, NULL) != 0)
234   {
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);
244     return false;
245   }
246
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);
248
249   return true;
250 }
251
252 void CEncoderFFmpeg::SetTag(const CStdString tag, const CStdString value)
253 {
254   m_dllAvUtil.av_dict_set(&m_Format->metadata, tag.c_str(), value.c_str(), 0);
255 }
256
257 int CEncoderFFmpeg::avio_write_callback(void *opaque, uint8_t *buf, int buf_size)
258 {
259   CEncoderFFmpeg *enc = (CEncoderFFmpeg*)opaque;
260   if(enc->FileWrite(buf, buf_size) != buf_size)
261   {
262     CLog::Log(LOGERROR, "Error writing FFmpeg buffer to file");
263     return -1;
264   }
265   return buf_size;
266 }
267
268 int64_t CEncoderFFmpeg::avio_seek_callback(void *opaque, int64_t offset, int whence)
269 {
270   CEncoderFFmpeg *enc = (CEncoderFFmpeg*)opaque;
271   return enc->FileSeek(offset, whence);
272 }
273
274 int CEncoderFFmpeg::Encode(int nNumBytesRead, BYTE* pbtStream)
275 {
276   while(nNumBytesRead > 0)
277   {
278     unsigned int space = m_NeededBytes - m_BufferSize;
279     unsigned int copy  = (unsigned int)nNumBytesRead > space ? space : nNumBytesRead;
280
281     memcpy(&m_Buffer[m_BufferSize], pbtStream, copy);
282     m_BufferSize  += copy;
283     pbtStream     += copy;
284     nNumBytesRead -= copy;
285
286     /* only write full packets */
287     if (m_BufferSize == m_NeededBytes)
288       if (!WriteFrame()) return 0;
289   }
290
291   return 1;
292 }
293
294 bool CEncoderFFmpeg::WriteFrame()
295 {
296   int encoded, got_output;
297   AVFrame* frame;
298
299   m_dllAvCodec.av_init_packet(&m_Pkt);
300   m_Pkt.data = NULL;
301   m_Pkt.size = 0;
302
303   if(m_NeedConversion)
304   {
305     if (m_dllSwResample.swr_convert(m_SwrCtx, m_ResampledFrame->extended_data, m_NeededFrames, (const uint8_t**)m_BufferFrame->extended_data, m_NeededFrames) < 0)
306     {
307       CLog::Log(LOGERROR, "CEncoderFFmpeg::WriteFrame - Error resampling audio");
308       return false;
309     }
310     frame = m_ResampledFrame;
311   }
312   else frame = m_BufferFrame;
313
314   encoded = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
315
316   m_BufferSize = 0;
317
318   if (encoded < 0) {
319     CLog::Log(LOGERROR, "CEncoderFFmpeg::WriteFrame - Error encoding audio: %i", encoded);
320     return false;
321   }
322
323   if (got_output)
324   {
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);
327
328     if (m_dllAvFormat.av_write_frame(m_Format, &m_Pkt) < 0) {
329       CLog::Log(LOGERROR, "CEncoderFFMmpeg::WriteFrame - Failed to write the frame data");
330       return false;
331     }
332   }
333
334   m_dllAvCodec.av_free_packet(&m_Pkt);
335
336   return true;
337 }
338
339 bool CEncoderFFmpeg::Close()
340 {
341   if (m_Format) {
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 */
347       WriteFrame();
348     }
349
350     /* Flush if needed */
351     m_dllAvUtil.av_freep(&m_Buffer);
352     m_dllAvCodec.avcodec_free_frame(&m_BufferFrame);
353
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;
358
359     WriteFrame();
360
361     /* write the trailer */
362     m_dllAvFormat.av_write_trailer(m_Format);
363     FlushStream();
364     FileClose();
365
366     /* cleanup */
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    );
371   }
372
373   m_BufferSize = 0;
374
375   m_dllAvFormat.Unload();
376   m_dllAvUtil  .Unload();
377   m_dllAvCodec .Unload();
378   m_dllSwResample.Unload();
379   return true;
380 }
381