2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
18 #include <unique_ptr.h>
19 #include <FBaseColHashMap.h>
20 #include <FBaseInteger.h>
21 #include <FMediaTypes.h>
22 #include <FBaseSysLog.h>
23 #include "FMedia_Ffmpeg.h"
24 #include "FMedia_AacEncoder.h"
26 using namespace Tizen::Base;
27 using namespace Tizen::Io;
28 using namespace Tizen::Base::Collection;
30 namespace Tizen { namespace Media
34 _AacEncoder_CreateInstance(void)
36 return new (std::nothrow) _AacEncoder();
39 _AacEncoder::_AacEncoder(void)
43 __pResampleContext = null;
48 _AacEncoder::~_AacEncoder(void)
50 if (__pCodecCtx != null)
52 avcodec_close(__pCodecCtx);
58 if (__pResampleContext != null)
60 audio_resample_close(__pResampleContext);
63 if (__pInputBuf != null)
68 if (__pInputFrame != null)
70 avcodec_free_frame(&__pInputFrame);
76 _AacEncoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
81 Integer* pValue = null;
86 SysTryReturnResult(NID_MEDIA, __pCodecCtx == null, E_INVALID_STATE, "already constructed");
88 avcodec_register_all();
90 __pCodec = avcodec_find_encoder(CODEC_ID_AAC);
91 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
92 "[%s] Failed to get avcodec encoder", GetErrorMessage(E_SYSTEM));
94 __pCodecCtx = avcodec_alloc_context3(__pCodec);
95 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
96 "[%s] Failed to allocate avcodec context", GetErrorMessage(E_SYSTEM));
99 __pCodecCtx->bit_rate = DEFAULT_BIT_RATE;
100 __pCodecCtx->sample_rate = DEFAULT_SAMPLE_RATE;
101 __pCodecCtx->channels = DEFAULT_CHANNEL_COUNT;
102 __pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT;
103 __pCodecCtx->profile = FF_PROFILE_AAC_LOW;
104 __pCodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
108 // The initialization values are given in the Hashmap
109 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
110 if (pMapEnum.get() != null)
112 while (pMapEnum.get()->MoveNext() == E_SUCCESS)
114 pKey = dynamic_cast<Integer*>(pMapEnum.get()->GetKey());
115 pValue = dynamic_cast<Integer*>(pMapEnum.get()->GetValue());
117 if (pKey == null || pValue == null)
123 value = pValue->ToInt();
126 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
127 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
128 E_OUT_OF_RANGE, "[%s] Audio Channel Type %d is outof range",GetErrorMessage(E_OUT_OF_RANGE));
129 __pCodecCtx->channels = value;
132 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
133 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
134 "[%s] Audio Sample rate is out of range", GetErrorMessage(E_OUT_OF_RANGE));
135 __pCodecCtx->sample_rate = value;
138 case MEDIA_PROPERTY_AUDIO_BIT_RATE:
139 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
140 "[%s] Audio Bit Rate is out of range",GetErrorMessage(E_OUT_OF_RANGE));
141 __pCodecCtx->bit_rate = value;
145 SysLog(NID_MEDIA,"[%s] Ignore option:%d", GetErrorMessage(E_INVALID_ARG),key);
153 if ( __pCodecCtx->bit_rate * SAMPLE_SIZE / __pCodecCtx->sample_rate
154 > __pCodecCtx->channels * BYTES_PER_SAMPLE)
156 __pCodecCtx->bit_rate = (__pCodecCtx->channels * BYTES_PER_SAMPLE)
157 / SAMPLE_SIZE * __pCodecCtx->sample_rate;
160 res = avcodec_open(__pCodecCtx, __pCodec);
161 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
162 "[%s] avcodec open failed:%d", GetErrorMessage(E_SYSTEM), res);
164 if (__pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
166 inputSize = __pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE;
167 __pInputBuf = new (std::nothrow) byte[inputSize];
168 SysTryCatch(NID_MEDIA, __pInputBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
169 "[%s] Memory Allocation Failed", GetErrorMessage(E_OUT_OF_MEMORY));
172 __pInputFrame = avcodec_alloc_frame();
173 SysTryCatch(NID_MEDIA, __pInputFrame != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
174 "[%s] Memory Allocation Failed", GetErrorMessage(E_OUT_OF_MEMORY));
176 __pInputFrame->nb_samples = __pCodecCtx->frame_size;
177 __pInputFrame->format = __pCodecCtx->sample_fmt;
178 __pInputFrame->channel_layout = __pCodecCtx->channel_layout;
184 if (__pCodecCtx != null)
186 avcodec_close(__pCodecCtx);
187 av_free(__pCodecCtx);
195 _AacEncoder::Encode(const byte* srcBuf, int& srcBufLength, byte*& dstBuf, int& dstBufLength)
197 result r = E_SUCCESS;
201 int minSrcBufLength = 0;
202 int minDstBufLength = FF_MIN_BUFFER_SIZE;
204 outPacket.data = null;
207 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
209 minSrcBufLength = __pCodecCtx->frame_size * S16_SAMPLE_SIZE * __pCodecCtx->channels;
211 SysTryCatch(NID_MEDIA, srcBuf != null && dstBuf != null, r = E_INVALID_ARG, E_INVALID_ARG,
212 "[%s] Invalid argument is used: 0x%x %d %d 0x%x %d %d",
213 GetErrorMessage(E_INVALID_ARG), srcBuf, srcBufLength, minSrcBufLength, dstBuf, dstBufLength, minDstBufLength);
215 //Partial frame encoding is supported hence no need of checking sourcebuf length.
216 SysTryCatch(NID_MEDIA, dstBufLength >= minDstBufLength,
217 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
218 "[%s] Destination Buffer Length is less than FF_MIN_BUFFER_SIZE: 0x%x %d %d 0x%x %d %d",
219 GetErrorMessage(E_OUT_OF_MEMORY), srcBuf, srcBufLength, minSrcBufLength, dstBuf, dstBufLength, minDstBufLength);
221 //Only AV_SAMPLE_FMT_FLT is supported by FFMpeg AAC Encoder hence Sample Format Conversion from S16 to Float
222 if (__pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
224 if (!__pResampleContext)
226 __pResampleContext = av_audio_resample_init(__pCodecCtx->channels, __pCodecCtx->channels,
227 __pCodecCtx->sample_rate, __pCodecCtx->sample_rate,
228 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
230 SysTryCatch(NID_MEDIA, __pResampleContext != null, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
231 "[%s] av audio resample init failed",GetErrorMessage(E_UNSUPPORTED_FORMAT));
235 memset(__pInputBuf,0,__pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE);
237 if(srcBufLength >= minSrcBufLength)
239 samples = audio_resample (__pResampleContext, (short *) __pInputBuf, (short *)srcBuf, __pCodecCtx->frame_size);
243 int sampleCount = srcBufLength/(__pCodecCtx->channels * S16_SAMPLE_SIZE);
244 samples = audio_resample (__pResampleContext, (short *) __pInputBuf, (short *)srcBuf,sampleCount);
248 res = avcodec_fill_audio_frame(__pInputFrame, __pCodecCtx->channels,__pCodecCtx->sample_fmt,
249 (const uint8_t*)__pInputBuf,__pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE,0 );
251 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
252 "[%s] Fill Audio Frame failed %d", GetErrorMessage(E_SYSTEM));
254 av_init_packet(&outPacket);
255 outPacket.data = NULL;
258 res = avcodec_encode_audio2(__pCodecCtx, &outPacket, __pInputFrame, &gotOutput);
260 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
261 "[%s] Audio Encode Failed %d", GetErrorMessage(E_SYSTEM));
265 memcpy(dstBuf,outPacket.data,outPacket.size);
266 dstBufLength = outPacket.size;
267 av_free_packet(&outPacket);
275 srcBufLength = minSrcBufLength; //Input bytes used
279 if (__pResampleContext != null)
281 audio_resample_close(__pResampleContext);
284 if(outPacket.data != null)
286 av_free_packet(&outPacket);
293 _AacEncoder::Reset(void)
295 result r = E_SUCCESS;
297 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
299 avcodec_flush_buffers(__pCodecCtx);