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");
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->rtp_payload_size = 1024;
104 __pCodecCtx->mb_decision = FF_MB_DECISION_BITS;
107 // The initialization values are given in the Hashmap
108 unique_ptr<IMapEnumerator> pMapEnum(pOption->GetMapEnumeratorN());
109 SysTryCatch(NID_MEDIA, pMapEnum.get() != null, r = E_SYSTEM, E_SYSTEM, "Propagating");
111 while (pMapEnum->MoveNext() == E_SUCCESS)
113 pKey = dynamic_cast<Integer*> (pMapEnum->GetKey());
114 pValue = dynamic_cast<Integer*> (pMapEnum->GetValue());
116 if (pKey == null || pValue == null)
122 value = pValue->ToInt();
127 case MEDIA_PROPERTY_VIDEO_WIDTH:
128 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
129 "[%s] Invalid argument is used: width %d", GetErrorMessage(E_INVALID_ARG), value);
130 __pCodecCtx->width = value;
133 case MEDIA_PROPERTY_VIDEO_HEIGHT:
134 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
135 "[%s] Invalid argument is used: height %d", GetErrorMessage(E_INVALID_ARG), value);
136 __pCodecCtx->height = value;
139 case MEDIA_PROPERTY_VIDEO_FRAME_RATE:
140 SysTryCatch(NID_MEDIA, value > 0, r = E_INVALID_ARG, E_INVALID_ARG,
141 "[%s] Invalid argument is used: frameRate %d", GetErrorMessage(E_INVALID_ARG), value);
142 __pCodecCtx->time_base.den = value;
143 __pCodecCtx->time_base.num = 1;
146 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
147 SysTryCatch(NID_MEDIA, value == MEDIA_PIXEL_FORMAT_YUV420P,
148 r = E_INVALID_ARG, E_INVALID_ARG,
149 "[%s] Invalid argument is used: pixelFormat %d", GetErrorMessage(E_INVALID_ARG), value);
150 __pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
153 case MEDIA_PROPERTY_VIDEO_BIT_RATE:
154 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
155 "[%s] Invalid argument is used: bitRate %d", GetErrorMessage(E_INVALID_ARG), value);
156 __pCodecCtx->bit_rate = value;
159 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN :
160 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
161 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization min %d", GetErrorMessage(E_INVALID_ARG), value);
162 __pCodecCtx->qmin = value;
165 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX :
166 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
167 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization max %d", GetErrorMessage(E_INVALID_ARG), value);
168 __pCodecCtx->qmax = value;
171 case MEDIA_PROPERTY_VIDEO_GOP_SIZE :
172 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
173 "[%s] Invalid argument is used: gop size %d", GetErrorMessage(E_INVALID_ARG), value);
174 __pCodecCtx->gop_size = value;
177 case MEDIA_PROPERTY_VIDEO_PROFILE:
178 SysTryCatch(NID_MEDIA, value == 0 || value == 3, r = E_INVALID_ARG, E_INVALID_ARG,
179 "[%s] Invalid argument is used: video profile %d", GetErrorMessage(E_INVALID_ARG), value);
180 __pCodecCtx->profile = value;
183 case MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE:
184 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
185 "[%s] Invalid argument is used: slice size %d", GetErrorMessage(E_INVALID_ARG), value);
186 __pCodecCtx->rtp_payload_size = value;
189 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER :
190 SysTryCatch(NID_MEDIA, value >= MIN_QP && value <= MAX_QP,
191 r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used: quantization max %d", GetErrorMessage(E_INVALID_ARG), value);
194 case MEDIA_PROPERTY_VIDEO_GOB_SIZE :
195 SysTryCatch(NID_MEDIA, value > 0 && value <= __pCodecCtx->height/16, r = E_INVALID_ARG, E_INVALID_ARG,
196 "[%s] Invalid argument is used: gob size %d", GetErrorMessage(E_INVALID_ARG), value);
199 case MEDIA_PROPERTY_VIDEO_USE_AC_PREDICTION :
200 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
201 "[%s] Invalid argument is used: ac prediction setting %d", GetErrorMessage(E_INVALID_ARG), value);
204 case MEDIA_PROPERTY_VIDEO_USE_HEADER_EXTENSION_CODE :
205 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
206 "[%s] Invalid argument is used: header extension code %d", GetErrorMessage(E_INVALID_ARG), value);
209 case MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP:
210 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG,
211 "[%s] Invalid argument is used: frame skip setting %d", GetErrorMessage(E_INVALID_ARG), value);
220 res = avcodec_open2(__pCodecCtx, __pCodec, null);
221 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
222 "[%s] avcodec open failed %d ", GetErrorMessage(E_SYSTEM), res);
224 __pFrame = avcodec_alloc_frame();
225 SysTryCatch(NID_MEDIA, __pFrame != null, r = E_SYSTEM, E_SYSTEM, "[%s] avcodec alloc frame failed", GetErrorMessage(E_SYSTEM));
227 for (int i = 0; i < 4; i++)
229 __pFrame->data[i] = null;
230 __pFrame->linesize[i] = 0;
238 if (__pCodecCtx != null)
240 avcodec_close(__pCodecCtx);
241 av_free(__pCodecCtx);
250 _H263Encoder::Encode(const byte* srcBuf, int& srcBufLength, byte*& dstBuf, int& dstBufLength)
252 result r = E_SUCCESS;
255 int minSrcBufLength = 0;
257 unique_ptr<AVPacket, _FfmpegDeleter> pPkt(null, ffmpegDeleter);
259 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
261 minSrcBufLength = __pCodecCtx->width * __pCodecCtx->height * 3 / 2;
262 SysTryCatch(NID_MEDIA, (srcBuf != null && dstBuf != null && srcBufLength >= minSrcBufLength
263 && dstBufLength >= FF_MIN_BUFFER_SIZE),
264 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
265 "[%s] Invalid argument is used. 0x%x %d %d 0x%x %d %d",
266 GetErrorMessage(E_OUT_OF_MEMORY), srcBuf, srcBufLength, minSrcBufLength, dstBuf, dstBufLength, FF_MIN_BUFFER_SIZE);
268 __pFrame->data[0] = (uint8_t*)srcBuf;
269 __pFrame->data[1] = (uint8_t*)srcBuf + __pCodecCtx->width * __pCodecCtx->height;
270 __pFrame->data[2] = (uint8_t*)srcBuf + __pCodecCtx->width * __pCodecCtx->height * 5 / 4;
271 __pFrame->linesize[0] = __pCodecCtx->width;
272 __pFrame->linesize[1] = __pCodecCtx->width / 2;
273 __pFrame->linesize[2] = __pCodecCtx->width / 2;
275 pPkt.reset(new (std::nothrow) AVPacket);
276 SysTryReturnResult(NID_MEDIA, pPkt.get() != null, E_OUT_OF_MEMORY, "new AVPacket failed.");
277 av_init_packet(pPkt.get());
278 pPkt->data = NULL; // packet data will be allocated by the encoder
281 res = avcodec_encode_video(__pCodecCtx, (uint8_t*) dstBuf+outIndex, dstBufLength, __pFrame);
282 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, "[%s] H263 Video Encode Failed %d", GetErrorMessage(E_SYSTEM), res);
283 srcBufLength = minSrcBufLength;
284 dstBufLength = res + outIndex;
289 res = avcodec_encode_video2(__pCodecCtx, pPkt.get(), __pFrame, &gotOutput);
290 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, "[%s] Video Encode Failed %d", GetErrorMessage(E_SYSTEM), res);
294 SysTryCatch(NID_MEDIA, pPkt->size <= dstBufLength, r = E_INVALID_ARG, E_INVALID_ARG,
295 "[%s] dst buffer is insufficient:%d %d", GetErrorMessage(E_INVALID_ARG), dstBufLength, pPkt->size);
296 memcpy(dstBuf+outIndex, pPkt->data, pPkt->size);
297 srcBufLength = minSrcBufLength;
298 dstBufLength = pPkt->size + outIndex;
302 srcBufLength = minSrcBufLength;
303 dstBufLength = outIndex;
312 _H263Encoder::Reset(void)
314 result r = E_SUCCESS;
316 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
317 avcodec_flush_buffers(__pCodecCtx);
322 _H263Encoder::SetValue(MediaPropertyType type, int value)
324 result r = E_SUCCESS;
326 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
327 SysTryCatch(NID_MEDIA, value >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
328 "[E_INVALID_ARG] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
329 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
330 "[E_INVALID_ARG] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
331 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH && type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
332 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Object not found. type:%d", GetErrorMessage(E_OBJ_NOT_FOUND), type);
336 case MEDIA_PROPERTY_VIDEO_WIDTH:
337 SysTryCatch(NID_MEDIA, value <= MAX_WIDTH, r = E_INVALID_ARG, E_INVALID_ARG,
338 "[%s] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
339 __pCodecCtx->width = value;
342 case MEDIA_PROPERTY_VIDEO_HEIGHT:
343 SysTryCatch(NID_MEDIA, value <= MAX_HEIGHT, r = E_INVALID_ARG, E_INVALID_ARG,
344 "[%s] Invalid argument is used. type:%d", GetErrorMessage(E_INVALID_ARG), type);
345 __pCodecCtx->height = value;
348 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
349 __pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
352 case MEDIA_PROPERTY_VIDEO_FRAME_RATE:
353 __pCodecCtx->time_base.den = 15;
354 __pCodecCtx->time_base.num = 1;
357 case MEDIA_PROPERTY_VIDEO_BIT_RATE:
358 __pCodecCtx->bit_rate = value;
361 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER :
362 __pCodecCtx->mpeg_quant = value;
365 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN :
366 __pCodecCtx->qmin = value;
369 case MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX :
370 __pCodecCtx->qmax = value;
373 case MEDIA_PROPERTY_VIDEO_GOP_SIZE :
374 __pCodecCtx->gop_size = value;
377 case MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE :
378 __pCodecCtx->rtp_payload_size = value;
381 return E_OBJ_NOT_FOUND;
391 _H263Encoder::SetValue(MediaPropertyType type, bool value)
393 result r = E_SUCCESS;
395 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "not constructed");
396 SysTryCatch(NID_MEDIA, type>0, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used",GetErrorMessage(E_INVALID_ARG));
397 SysTryCatch(NID_MEDIA, value == 0 || value == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] Invalid argument is used.",GetErrorMessage(E_INVALID_ARG));
398 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH || type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
399 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[%s] Object not found", GetErrorMessage(E_OBJ_NOT_FOUND));
402 case MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME:
403 __pCodecCtx->skip_frame = AVDISCARD_DEFAULT;
406 case MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING:
407 __pCodecCtx->skip_idct = AVDISCARD_DEFAULT;
411 return E_OBJ_NOT_FOUND;
422 Tizen::Base::Collection::IListT<MediaPropertyType>*
423 _H263Encoder::GetSupportedPropertyListN(void) const
425 result r = E_SUCCESS;
426 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
428 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
429 "[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
430 pPropList->Add(MEDIA_PROPERTY_VIDEO_WIDTH);
431 pPropList->Add(MEDIA_PROPERTY_VIDEO_HEIGHT);
432 pPropList->Add(MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT);
433 pPropList->Add(MEDIA_PROPERTY_VIDEO_FRAME_RATE);
434 pPropList->Add(MEDIA_PROPERTY_VIDEO_BIT_RATE);
435 pPropList->Add(MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER);
436 pPropList->Add( MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX);
437 pPropList->Add(MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN);
438 pPropList->Add(MEDIA_PROPERTY_VIDEO_GOP_SIZE);
439 pPropList->Add(MEDIA_PROPERTY_VIDEO_PROFILE);
440 pPropList->Add(MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP);
441 pPropList->Add(MEDIA_PROPERTY_VIDEO_GOB_SIZE);
442 pPropList->Add(MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE);
443 pPropList->Add(MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME);
444 pPropList->Add(MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING);
454 _H263Encoder::IsPropertySupported(MediaPropertyType type) const
456 result r = E_SUCCESS;
458 SysTryReturn(NID_MEDIA, __pCodecCtx, false, E_INVALID_STATE, "[E_INVALID_STATE] not constructed");
459 SysTryCatch(NID_MEDIA, ( type == MEDIA_PROPERTY_VIDEO_WIDTH || type == MEDIA_PROPERTY_VIDEO_HEIGHT
460 || type == MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT || type == MEDIA_PROPERTY_VIDEO_FRAME_RATE
461 || type == MEDIA_PROPERTY_VIDEO_BIT_RATE || type == MEDIA_PROPERTY_VIDEO_QUANTIZATION_PARAMETER || type ==
462 MEDIA_PROPERTY_VIDEO_QUANTIZATION_MIN || type == MEDIA_PROPERTY_VIDEO_QUANTIZATION_MAX || type == MEDIA_PROPERTY_VIDEO_GOP_SIZE || type ==
463 MEDIA_PROPERTY_VIDEO_PROFILE || type == MEDIA_PROPERTY_VIDEO_USE_FRAME_SKIP || type == MEDIA_PROPERTY_VIDEO_GOB_SIZE || type ==
464 MEDIA_PROPERTY_VIDEO_SLICE_SIZE_IN_BYTE || type == MEDIA_PROPERTY_VIDEO_FORCE_SKIP_FRAME || type == MEDIA_PROPERTY_VIDEO_FORCE_INTRA_CODING),
465 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
466 "[%s] Object not found %d", GetErrorMessage(E_OBJ_NOT_FOUND), type);