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>
20 #include <FBaseColArrayListT.h>
21 #include <FBaseColHashMap.h>
22 #include <FBaseInteger.h>
23 #include <FMediaTypes.h>
24 #include <FBaseSysLog.h>
25 #include "FMedia_Ffmpeg.h"
26 #include "FMedia_IVideoEncoder.h"
27 #include "FMedia_H263Encoder.h"
30 using namespace Tizen::Base;
31 using namespace Tizen::Io;
32 using namespace Tizen::Base::Collection;
34 namespace Tizen { namespace Media
38 _H263Encoder_CreateInstance(void)
40 return new (std::nothrow) _H263Encoder();
43 _H263Encoder::_H263Encoder(void)
51 _H263Encoder::~_H263Encoder(void)
53 if (__pCodecCtx != null)
55 avcodec_close(__pCodecCtx);
68 _H263Encoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
73 Integer* pValue = null;
77 SysTryReturnResult(NID_MEDIA, __pCodecCtx == null, E_INVALID_STATE, "already constructed");
79 av_log_set_level (AV_LOG_QUIET);
80 avcodec_register_all();
82 __pCodec = avcodec_find_encoder(CODEC_ID_H263P);
83 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM, "[%s] Failed to get avcodec encoder",GetErrorMessage(E_SYSTEM));
85 __pCodecCtx = avcodec_alloc_context3(__pCodec);
86 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
87 "[%s] Failed to allocate avcodec context", GetErrorMessage(E_SYSTEM));
89 __pCodecCtx->bit_rate = BITRATE_IN_BITS;
90 __pCodecCtx->width = WIDTH;
91 __pCodecCtx->height = HEIGHT;
92 __pCodecCtx->time_base.den = 15;
93 __pCodecCtx->time_base.num = 1;
94 __pCodecCtx->gop_size = GOP ;
95 __pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
96 __pCodecCtx->thread_count = 1;
97 __pCodecCtx->max_b_frames = 0;
99 __pCodecCtx->qmin = MIN_QP;
100 __pCodecCtx->qmax = MAX_QP;
101 __pCodecCtx->mpeg_quant = 0;
102 __pCodecCtx->profile = 0;
103 __pCodecCtx->mb_decision = FF_MB_DECISION_BITS;
106 // The initialization values are given in the Hashmap
107 unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
108 SysTryCatch(NID_MEDIA, pMapEnum.get() != null, r = E_SYSTEM, E_SYSTEM, "Propagating");
110 while (pMapEnum->MoveNext() == E_SUCCESS)
112 pKey = dynamic_cast<Integer*> (pMapEnum->GetKey());
113 pValue = dynamic_cast<Integer*> (pMapEnum->GetValue());
115 if (pKey == null || pValue == null)
121 value = pValue->ToInt();
126 case MEDIA_PROPERTY_VIDEO_WIDTH:
127 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
128 "[%s] Invalid argument is used: width %d", GetErrorMessage(E_INVALID_ARG), value);
129 __pCodecCtx->width = value;
132 case MEDIA_PROPERTY_VIDEO_HEIGHT:
133 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
134 "[%s] Invalid argument is used: height %d", GetErrorMessage(E_INVALID_ARG), value);
135 __pCodecCtx->height = value;
138 case MEDIA_PROPERTY_VIDEO_FRAME_RATE:
139 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
140 "[%s] Invalid argument is used: frameRate %d", GetErrorMessage(E_INVALID_ARG), value);
141 __pCodecCtx->time_base.den = value;
142 __pCodecCtx->time_base.num = 1;
145 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
146 SysTryCatch(NID_MEDIA, value == MEDIA_PIXEL_FORMAT_YUV420P,
147 r = E_INVALID_ARG, E_INVALID_ARG,
148 "[%s] Invalid argument is used: pixelFormat %d", GetErrorMessage(E_INVALID_ARG), value);
149 __pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
152 case MEDIA_PROPERTY_VIDEO_BIT_RATE:
153 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
154 "[%s] Invalid argument is used: bitRate %d", GetErrorMessage(E_INVALID_ARG), value);
155 __pCodecCtx->bit_rate = value;
158 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN :
159 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
160 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization min %d", GetErrorMessage(E_INVALID_ARG), value);
161 __pCodecCtx->qmin = value;
164 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX :
165 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
166 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization max %d", GetErrorMessage(E_INVALID_ARG), value);
167 __pCodecCtx->qmax = value;
170 case MEDIA_PROPERTY_VIDEO_GOP_SIZE :
171 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
172 "[%s] Invalid argument is used: gop size %d", GetErrorMessage(E_INVALID_ARG), value);
173 __pCodecCtx->gop_size = value;
176 case MEDIA_PROPERTY_VIDEO_PROFILE:
177 SysTryCatch(NID_MEDIA, value == 0 || value == 3, r = E_INVALID_ARG, E_INVALID_ARG,
178 "[%s] Invalid argument is used: video profile %d", GetErrorMessage(E_INVALID_ARG), value);
179 __pCodecCtx->profile = value;
182 case MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE:
183 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
184 "[%s] Invalid argument is used: slice size %d", GetErrorMessage(E_INVALID_ARG), value);
185 __pCodecCtx->rtp_payload_size = value;
188 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER :
189 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
190 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization max %d", GetErrorMessage(E_INVALID_ARG), value);
193 case MEDIA_PROPERTY_VIDEO_GOB_SIZE :
194 SysTryCatch(NID_MEDIA, value > 0 && value <= __pCodecCtx->height/16, r = E_INVALID_ARG, E_INVALID_ARG,
195 "[%s] Invalid argument is used: gob size %d", GetErrorMessage(E_INVALID_ARG), value);
198 case MEDIA_PROPERTY_VIDEO_USE_AC_PREDICTION :
199 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
200 "[%s] Invalid argument is used: ac prediction setting %d", GetErrorMessage(E_INVALID_ARG), value);
203 case MEDIA_PROPERTY_VIDEO_USE_HEADER_EXTENSION_CODE :
204 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
205 "[%s] Invalid argument is used: header extension code %d", GetErrorMessage(E_INVALID_ARG), value);
208 case MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP:
209 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
210 "[%s] Invalid argument is used: frame skip setting %d", GetErrorMessage(E_INVALID_ARG), value);
219 res = avcodec_open2(__pCodecCtx, __pCodec, null);
220 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
221 "[%s] avcodec open failed %d ", GetErrorMessage(E_SYSTEM), res);
223 __pFrame = avcodec_alloc_frame();
224 SysTryCatch(NID_MEDIA, __pFrame != null, r = E_SYSTEM, E_SYSTEM, "[%s] avcodec alloc frame failed", GetErrorMessage(E_SYSTEM));
226 for (int i = 0; i < 4; i++)
228 __pFrame->data[i] = null;
229 __pFrame->linesize[i] = 0;
237 if (__pCodecCtx != null)
239 avcodec_close(__pCodecCtx);
240 av_free(__pCodecCtx);
249 _H263Encoder::Encode(const byte* srcBuf, int& srcBufLength, byte*& dstBuf, int& dstBufLength)
251 result r = E_SUCCESS;
254 int minSrcBufLength = 0;
256 unique_ptr<AVPacket, _FfmpegDeleter> pPkt(null, ffmpegDeleter);
258 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
260 minSrcBufLength = __pCodecCtx->width * __pCodecCtx->height * 3 / 2;
261 SysTryCatch(NID_MEDIA, (srcBuf != null && dstBuf != null && srcBufLength >= minSrcBufLength
262 && dstBufLength >= FF_MIN_BUFFER_SIZE),
263 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
264 "[%s] Invalid argument is used. 0x%x %d %d 0x%x %d %d",
265 GetErrorMessage(E_OUT_OF_MEMORY), srcBuf, srcBufLength, minSrcBufLength, dstBuf, dstBufLength, FF_MIN_BUFFER_SIZE);
267 __pFrame->data[0] = (uint8_t*)srcBuf;
268 __pFrame->data[1] = (uint8_t*)srcBuf + __pCodecCtx->width * __pCodecCtx->height;
269 __pFrame->data[2] = (uint8_t*)srcBuf + __pCodecCtx->width * __pCodecCtx->height * 5 / 4;
270 __pFrame->linesize[0] = __pCodecCtx->width;
271 __pFrame->linesize[1] = __pCodecCtx->width / 2;
272 __pFrame->linesize[2] = __pCodecCtx->width / 2;
274 pPkt.reset(new (std::nothrow) AVPacket);
275 SysTryReturnResult(NID_MEDIA, pPkt.get() != null, E_OUT_OF_MEMORY, "new AVPacket failed.");
276 av_init_packet(pPkt.get());
277 pPkt->data = NULL; // packet data will be allocated by the encoder
280 res = avcodec_encode_video(__pCodecCtx, (uint8_t*) dstBuf+outIndex, dstBufLength, __pFrame);
281 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, "[%s] H263 Video Encode Failed %d", GetErrorMessage(E_SYSTEM), res);
282 srcBufLength = minSrcBufLength;
283 dstBufLength = res + outIndex;
288 res = avcodec_encode_video2(__pCodecCtx, pPkt.get(), __pFrame, &gotOutput);
289 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, "[%s] Video Encode Failed %d", GetErrorMessage(E_SYSTEM), res);
293 SysTryCatch(NID_MEDIA, pPkt->size <= dstBufLength, r = E_INVALID_ARG, E_INVALID_ARG,
294 "[%s] dst buffer is insufficient:%d %d", GetErrorMessage(E_INVALID_ARG), dstBufLength, pPkt->size);
295 memcpy(dstBuf+outIndex, pPkt->data, pPkt->size);
296 srcBufLength = minSrcBufLength;
297 dstBufLength = pPkt->size + outIndex;
301 srcBufLength = minSrcBufLength;
302 dstBufLength = outIndex;
311 _H263Encoder::Reset(void)
313 result r = E_SUCCESS;
315 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
316 avcodec_flush_buffers(__pCodecCtx);
321 _H263Encoder::SetValue(MediaPropertyType type, int value)
323 result r = E_SUCCESS;
325 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
326 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
327 "[E_INVALID_ARG] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
328 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
329 "[E_INVALID_ARG] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
330 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH && type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
331 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Object not found. type:%d", GetErrorMessage(E_OBJ_NOT_FOUND), type);
335 case MEDIA_PROPERTY_VIDEO_WIDTH:
336 SysTryCatch(NID_MEDIA, value <= MAX_WIDTH, r = E_INVALID_ARG, E_INVALID_ARG,
337 "[%s] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
338 __pCodecCtx->width = value;
341 case MEDIA_PROPERTY_VIDEO_HEIGHT:
342 SysTryCatch(NID_MEDIA, value <= MAX_HEIGHT, r = E_INVALID_ARG, E_INVALID_ARG,
343 "[%s] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
344 __pCodecCtx->height = value;
347 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
348 __pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
351 case MEDIA_PROPERTY_VIDEO_FRAME_RATE:
352 __pCodecCtx->time_base.den = 15;
353 __pCodecCtx->time_base.num = 1;
356 case MEDIA_PROPERTY_VIDEO_BIT_RATE:
357 __pCodecCtx->bit_rate = value;
360 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER :
361 __pCodecCtx->mpeg_quant = value;
364 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN :
365 __pCodecCtx->qmin = value;
368 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX :
369 __pCodecCtx->qmax = value;
372 case MEDIA_PROPERTY_VIDEO_GOP_SIZE :
373 __pCodecCtx->gop_size = value;
376 case MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE :
377 __pCodecCtx->rtp_payload_size = value;
380 return E_OBJ_NOT_FOUND;
390 _H263Encoder::SetValue(MediaPropertyType type, bool value)
392 result r = E_SUCCESS;
394 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
395 SysTryCatch(NID_MEDIA, type>0, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used",GetErrorMessage(E_INVALID_ARG));
396 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used.",GetErrorMessage(E_INVALID_ARG));
397 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH || type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
398 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[%s] Object not found", GetErrorMessage(E_OBJ_NOT_FOUND));
401 case MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME:
402 __pCodecCtx->skip_frame = AVDISCARD_DEFAULT;
405 case MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING:
406 __pCodecCtx->skip_idct = AVDISCARD_DEFAULT;
410 return E_OBJ_NOT_FOUND;
421 Tizen::Base::Collection::IListT<MediaPropertyType>*
422 _H263Encoder::GetSupportedPropertyListN(void) const
424 result r = E_SUCCESS;
425 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
427 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
428 "[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
429 pPropList->Add(MEDIA_PROPERTY_VIDEO_WIDTH);
430 pPropList->Add(MEDIA_PROPERTY_VIDEO_HEIGHT);
431 pPropList->Add(MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT);
432 pPropList->Add(MEDIA_PROPERTY_VIDEO_FRAME_RATE);
433 pPropList->Add(MEDIA_PROPERTY_VIDEO_BIT_RATE);
434 pPropList->Add(MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER);
435 pPropList->Add( MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX);
436 pPropList->Add(MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN);
437 pPropList->Add(MEDIA_PROPERTY_VIDEO_GOP_SIZE);
438 pPropList->Add(MEDIA_PROPERTY_VIDEO_PROFILE);
439 pPropList->Add(MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP);
440 pPropList->Add(MEDIA_PROPERTY_VIDEO_GOB_SIZE);
441 pPropList->Add(MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE);
442 pPropList->Add(MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME);
443 pPropList->Add(MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING);
453 _H263Encoder::IsPropertySupported(MediaPropertyType type) const
455 result r = E_SUCCESS;
457 SysTryReturn(NID_MEDIA, __pCodecCtx, false, E_INVALID_STATE, "[E_INVALID_STATE] not constructed");
458 SysTryCatch(NID_MEDIA, ( type == MEDIA_PROPERTY_VIDEO_WIDTH || type == MEDIA_PROPERTY_VIDEO_HEIGHT
459 || type == MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT || type == MEDIA_PROPERTY_VIDEO_FRAME_RATE
460 || type == MEDIA_PROPERTY_VIDEO_BIT_RATE || type == MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER || type ==
461 MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN || type == MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX || type == MEDIA_PROPERTY_VIDEO_GOP_SIZE || type ==
462 MEDIA_PROPERTY_VIDEO_PROFILE || type == MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP || type == MEDIA_PROPERTY_VIDEO_GOB_SIZE || type ==
463 MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE || type == MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME || type == MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING),
464 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
465 "[%s] Object not found %d", GetErrorMessage(E_OBJ_NOT_FOUND), type);