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 av_log_set_level (AV_LOG_QUIET);
89 avcodec_register_all();
91 __pCodec = avcodec_find_encoder(CODEC_ID_AAC);
92 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
93 "[%s] Failed to get avcodec encoder", GetErrorMessage(E_SYSTEM));
95 __pCodecCtx = avcodec_alloc_context3(__pCodec);
96 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
97 "[%s] Failed to allocate avcodec context", GetErrorMessage(E_SYSTEM));
100 __pCodecCtx->bit_rate = DEFAULT_BIT_RATE;
101 __pCodecCtx->sample_rate = DEFAULT_SAMPLE_RATE;
102 __pCodecCtx->channels = DEFAULT_CHANNEL_COUNT;
103 __pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT;
104 __pCodecCtx->profile = FF_PROFILE_AAC_LOW;
105 __pCodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
109 // The initialization values are given in the Hashmap
110 std::unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
111 if (pMapEnum.get() != null)
113 while (pMapEnum.get()->MoveNext() == E_SUCCESS)
115 pKey = dynamic_cast<Integer*>(pMapEnum.get()->GetKey());
116 pValue = dynamic_cast<Integer*>(pMapEnum.get()->GetValue());
118 if (pKey == null || pValue == null)
124 value = pValue->ToInt();
127 case MEDIA_PROPERTY_AUDIO_CHANNEL_TYPE:
128 SysTryCatch(NID_MEDIA, (value == 0 || value == 1 || value == 2), r = E_OUT_OF_RANGE,
129 E_OUT_OF_RANGE, "[%s] Audio Channel Type %d is outof range",GetErrorMessage(E_OUT_OF_RANGE));
130 __pCodecCtx->channels = value;
133 case MEDIA_PROPERTY_AUDIO_SAMPLE_RATE:
134 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
135 "[%s] Audio Sample rate is out of range", GetErrorMessage(E_OUT_OF_RANGE));
136 __pCodecCtx->sample_rate = value;
139 case MEDIA_PROPERTY_AUDIO_BIT_RATE:
140 SysTryCatch(NID_MEDIA, !(value < 0), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE,
141 "[%s] Audio Bit Rate is out of range",GetErrorMessage(E_OUT_OF_RANGE));
142 __pCodecCtx->bit_rate = value;
146 SysLog(NID_MEDIA,"[%s] Ignore option:%d", GetErrorMessage(E_INVALID_ARG),key);
154 if ( __pCodecCtx->bit_rate * SAMPLE_SIZE / __pCodecCtx->sample_rate
155 > __pCodecCtx->channels * BYTES_PER_SAMPLE)
157 __pCodecCtx->bit_rate = (__pCodecCtx->channels * BYTES_PER_SAMPLE)
158 / SAMPLE_SIZE * __pCodecCtx->sample_rate;
161 res = avcodec_open2(__pCodecCtx, __pCodec, null);
162 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
163 "[%s] avcodec open failed:%d", GetErrorMessage(E_SYSTEM), res);
165 if (__pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
167 inputSize = __pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE;
168 __pInputBuf = new (std::nothrow) byte[inputSize];
169 SysTryCatch(NID_MEDIA, __pInputBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
170 "[%s] Memory Allocation Failed", GetErrorMessage(E_OUT_OF_MEMORY));
173 __pInputFrame = avcodec_alloc_frame();
174 SysTryCatch(NID_MEDIA, __pInputFrame != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
175 "[%s] Memory Allocation Failed", GetErrorMessage(E_OUT_OF_MEMORY));
177 __pInputFrame->nb_samples = __pCodecCtx->frame_size;
178 __pInputFrame->format = __pCodecCtx->sample_fmt;
179 __pInputFrame->channel_layout = __pCodecCtx->channel_layout;
185 if (__pCodecCtx != null)
187 avcodec_close(__pCodecCtx);
188 av_free(__pCodecCtx);
196 _AacEncoder::Encode(const byte* srcBuf, int srcBufSize, int &srcBufUsed, byte* dstBuf, int dstBufSize, int &dstBufUsed)
198 result r = E_SUCCESS;
201 int minSrcBufLength = 0;
202 int minDstBufLength = FF_MIN_BUFFER_SIZE;
205 outPacket.data = NULL;
206 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
208 minSrcBufLength = __pCodecCtx->frame_size * S16_SAMPLE_SIZE * __pCodecCtx->channels;
210 SysTryCatch(NID_MEDIA, srcBuf != null && dstBuf != null, r = E_INVALID_ARG, E_INVALID_ARG,
211 "[%s] Invalid argument is used: 0x%x %d %d 0x%x %d %d",
212 GetErrorMessage(E_INVALID_ARG), srcBuf, srcBufSize, minSrcBufLength, dstBuf, dstBufSize, minDstBufLength);
214 //Partial frame encoding is supported hence no need of checking sourcebuf length.
215 SysTryCatch(NID_MEDIA, dstBufSize >= minDstBufLength,
216 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
217 "[%s] Destination Buffer Length is less than FF_MIN_BUFFER_SIZE: 0x%x %d %d 0x%x %d %d",
218 GetErrorMessage(E_OUT_OF_MEMORY), srcBuf, srcBufSize, minSrcBufLength, dstBuf, dstBufSize, minDstBufLength);
220 //Only AV_SAMPLE_FMT_FLT is supported by FFMpeg AAC Encoder hence Sample Format Conversion from S16 to Float
221 if (__pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
223 if (!__pResampleContext)
225 __pResampleContext = av_audio_resample_init(__pCodecCtx->channels, __pCodecCtx->channels,
226 __pCodecCtx->sample_rate, __pCodecCtx->sample_rate,
227 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
229 SysTryCatch(NID_MEDIA, __pResampleContext != null, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
230 "[%s] av audio resample init failed",GetErrorMessage(E_UNSUPPORTED_FORMAT));
234 memset(__pInputBuf,0,__pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE);
236 if(srcBufSize >= minSrcBufLength)
238 samples = audio_resample (__pResampleContext, (short *) __pInputBuf, (short *)srcBuf, __pCodecCtx->frame_size);
242 int sampleCount = srcBufSize/(__pCodecCtx->channels * S16_SAMPLE_SIZE);
243 samples = audio_resample (__pResampleContext, (short *) __pInputBuf, (short *)srcBuf,sampleCount);
247 res = avcodec_fill_audio_frame(__pInputFrame, __pCodecCtx->channels,__pCodecCtx->sample_fmt,
248 (const uint8_t*)__pInputBuf,__pCodecCtx->frame_size * __pCodecCtx->channels * FLT_SAMPLE_SIZE,0 );
250 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
251 "[%s] Fill Audio Frame failed %d", GetErrorMessage(E_SYSTEM));
253 av_init_packet(&outPacket);
254 outPacket.data = NULL;
256 outPacket.priv = 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 dstBufUsed = outPacket.size;
267 av_free_packet(&outPacket);
275 srcBufUsed = 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);