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.
19 #include <FBaseColArrayListT.h>
20 #include <FBaseColHashMap.h>
21 #include <FMediaTypes.h>
22 #include <FBaseSysLog.h>
23 #include "FMedia_Ffmpeg.h"
24 #include "FMedia_IVideoDecoder.h"
25 #include "FMedia_H263Decoder.h"
27 using namespace Tizen::Base;
28 using namespace Tizen::Io;
29 using namespace Tizen::Base::Collection;
31 namespace Tizen { namespace Media
35 _H263Decoder_CreateInstance(void)
37 return new (std::nothrow) _H263Decoder();
40 _H263Decoder::_H263Decoder(void)
44 __isDecodeCalled = false;
47 _H263Decoder::~_H263Decoder(void)
49 if (__pCodecCtx != null)
51 avcodec_flush_buffers(__pCodecCtx);
52 avcodec_close(__pCodecCtx);
60 _H263Decoder::Construct(const Tizen::Base::Collection::HashMap* pOption)
65 SysAssertf((__pCodecCtx == null && __pCodec == null), " Already Constructed .");
\r
67 av_log_set_level (AV_LOG_QUIET);
68 avcodec_register_all();
70 __pCodec = avcodec_find_decoder(CODEC_ID_H263);
71 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
72 "[%s] AVCODEC Find Decoder Failed for CODEC_ID_H263",GetErrorMessage(E_SYSTEM));
74 __pCodecCtx = avcodec_alloc_context3(__pCodec);
75 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
76 "[%s] AVCODEC Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
\r
78 res = avcodec_open2(__pCodecCtx, __pCodec, null);
79 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
80 "[%s] AVCODEC Codec Open Failed for CODEC_ID_H263",GetErrorMessage(E_SYSTEM));
\r
82 // AVCodecContext parameters
83 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
85 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
88 __pCodecCtx->debug_mv = 0; //set by user
89 __pCodecCtx->debug = 0; //set by user
90 __pCodecCtx->workaround_bugs = 1; //set by user
91 __pCodecCtx->lowres = 0; //set by user
92 __pCodecCtx->skip_frame = AVDISCARD_DEFAULT; //set by user
93 __pCodecCtx->skip_idct = AVDISCARD_DEFAULT; //set by user
94 __pCodecCtx->skip_loop_filter = AVDISCARD_DEFAULT; //set by user
99 if (__pCodecCtx != null)
101 avcodec_close(__pCodecCtx);
109 _H263Decoder::Decode(const byte* pSrcBuf, int& srcBufLength,
110 byte*& pDstBuf, int& dstBufLength, bool& gotFrame)
112 result r = E_SUCCESS;
114 AVFrame* pVideoFrame = null;
115 AVPacket inputPacket;
117 int remainingBytes = 0;
122 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
123 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && pDstBuf != null && srcBufLength > 0 && dstBufLength > 0),
124 E_INVALID_ARG, "Invalid argument is used. The argument is not valid");
\r
126 av_init_packet(&inputPacket);
127 inputPacket.size = srcBufLength;
128 pVideoFrame = avcodec_alloc_frame();
129 SysTryCatch(NID_MEDIA, pVideoFrame != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
130 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
132 inputPacket.data = (uint8_t*) pSrcBuf;
133 // Decoding the video packet
134 remainingBytes = srcBufLength;
138 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
139 SysTryCatch(NID_MEDIA, res >= 0, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
140 "[%s] The input data format is not supported ", GetErrorMessage(E_UNSUPPORTED_FORMAT));
\r
142 remainingBytes -= res;
143 inputPacket.data += res;
144 inputPacket.size -= res;
148 __isDecodeCalled = true;
149 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
151 SysTryCatch(NID_MEDIA, dstBufLength >= (__pCodecCtx->height*__pCodecCtx->width*3)/2,
152 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
153 "[%s] pDstBuf:%d %d %d",GetErrorMessage(E_OUT_OF_MEMORY),
\r
154 dstBufLength, __pCodecCtx->height, __pCodecCtx->width);
155 for (i = 0; i < __pCodecCtx->height; i++)
157 srcOffset = i * pVideoFrame->linesize[0];
158 offset = i * __pCodecCtx->width;
159 memcpy(pDstBuf + offset, pVideoFrame->data[0] + srcOffset, __pCodecCtx->width);
161 for (i = 0; i < __pCodecCtx->height / 2; i++)
163 srcOffset = i * pVideoFrame->linesize[1];
164 offset = (__pCodecCtx->height * __pCodecCtx->width) + (i * __pCodecCtx->width) / 2;
165 memcpy(pDstBuf + offset, pVideoFrame->data[1] + srcOffset, __pCodecCtx->width / 2);
167 for (i = 0; i < __pCodecCtx->height / 2; i++)
169 srcOffset = i * pVideoFrame->linesize[2];
170 offset = ((__pCodecCtx->height * __pCodecCtx->width * 5) / 4) + (i * __pCodecCtx->width) / 2;
171 memcpy(pDstBuf + offset, pVideoFrame->data[2] + srcOffset, __pCodecCtx->width / 2);
174 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
175 dstBufLength = (__pCodecCtx->height * __pCodecCtx->width * 3) / 2;
180 while (remainingBytes);
184 // "Trying for another decode"
185 inputPacket.data = null;
186 inputPacket.size = 0;
187 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
191 __isDecodeCalled = true;
192 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P ) // handling only yuv 420 case
194 SysTryCatch(NID_MEDIA, dstBufLength >= (__pCodecCtx->height*__pCodecCtx->width*3)/2,
195 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
196 "[%s] Decode Failed Insufficient destination buffer",GetErrorMessage(E_OUT_OF_MEMORY));
\r
197 for (i = 0; i < __pCodecCtx->height; i++)
199 srcOffset = i * pVideoFrame->linesize[0];
200 offset = i * __pCodecCtx->width;
201 memcpy(pDstBuf + offset, pVideoFrame->data[0] + srcOffset, __pCodecCtx->width);
203 for (i = 0; i < __pCodecCtx->height / 2; i++)
205 srcOffset = i * pVideoFrame->linesize[1];
206 offset = (__pCodecCtx->height * __pCodecCtx->width) + (i * __pCodecCtx->width) / 2;
207 memcpy(pDstBuf + offset, pVideoFrame->data[1] + srcOffset, __pCodecCtx->width / 2);
209 for (i = 0; i < __pCodecCtx->height / 2; i++)
211 srcOffset = i * pVideoFrame->linesize[2];
212 offset = ((__pCodecCtx->height * __pCodecCtx->width * 5) / 4) + (i * __pCodecCtx->width) / 2;
213 memcpy(pDstBuf + offset, pVideoFrame->data[2] + srcOffset, __pCodecCtx->width / 2);
216 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
217 dstBufLength = (__pCodecCtx->height * __pCodecCtx->width * 3) / 2;
223 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
228 av_free(pVideoFrame);
233 if (pVideoFrame != null)
235 av_free(pVideoFrame);
238 SysLog(NID_MEDIA, "Error is %d.", res);
243 _H263Decoder::Probe(const byte* pSrcBuf, const int srcBufLength, int& width, int& height,
244 MediaPixelFormat& pixelFormat)
246 result r = E_SUCCESS;
248 AVFrame* pVideoFrame = null;
249 AVPacket inputPacket;
251 int remainingBytes = 0;
253 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
254 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && srcBufLength > 0), E_INVALID_ARG,
255 "Invalid argument is used. The argument is not valid");
\r
257 av_init_packet(&inputPacket);
258 inputPacket.size = srcBufLength + FF_INPUT_BUFFER_PADDING_SIZE;
259 pVideoFrame = avcodec_alloc_frame();
261 SysTryCatch(NID_MEDIA, (pVideoFrame != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
262 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
263 inputPacket.data = (uint8_t*) pSrcBuf;
265 // Decoding the video packet
266 remainingBytes = inputPacket.size;
270 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
271 SysTryCatch(NID_MEDIA, res >= 0, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
272 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
277 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
279 width = __pCodecCtx->width;
280 height = __pCodecCtx->height;
281 pixelFormat = MEDIA_PIXEL_FORMAT_YUV420P;
286 remainingBytes -= res;
287 inputPacket.data += res;
288 inputPacket.size -= res;
290 while (remainingBytes);
294 inputPacket.data = null;
295 inputPacket.size = 0;
296 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
297 if (gotPicture && res >= 0)
300 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
302 width = __pCodecCtx->width;
303 height = __pCodecCtx->height;
304 pixelFormat = MEDIA_PIXEL_FORMAT_YUV420P;
309 r = E_UNSUPPORTED_FORMAT;
313 if (pVideoFrame != null)
315 av_free(pVideoFrame);
320 if (pVideoFrame != null)
322 av_free(pVideoFrame);
328 _H263Decoder::Reset(void)
330 result r = E_SUCCESS;
332 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
333 avcodec_flush_buffers(__pCodecCtx);
334 __isDecodeCalled = false;
340 _H263Decoder::GetValue(MediaPropertyType type, int& value) const
342 result r = E_SUCCESS;
344 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
345 SysTryCatch(NID_MEDIA, __isDecodeCalled == true, r = E_INVALID_STATE, E_INVALID_STATE,
346 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
347 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
348 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
349 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH && type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
350 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
351 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r
355 case MEDIA_PROPERTY_VIDEO_WIDTH:
356 value = __pCodecCtx->width;
359 case MEDIA_PROPERTY_VIDEO_HEIGHT:
360 value = __pCodecCtx->height;
363 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
364 value = MEDIA_PIXEL_FORMAT_YUV420P;
368 return E_OBJ_NOT_FOUND;
378 _H263Decoder::GetValue(MediaPropertyType type, float& value) const
380 result r = E_SUCCESS;
382 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not constructed");
383 SysTryCatch(NID_MEDIA, __isDecodeCalled == true, r = E_INVALID_STATE, E_INVALID_STATE,
384 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
385 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
386 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
387 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH || type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
388 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r
390 return E_OBJ_NOT_FOUND;
396 Tizen::Base::Collection::IListT<MediaPropertyType>*
397 _H263Decoder::GetSupportedPropertyListN(void) const
399 result r = E_SUCCESS;
401 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
402 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
403 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
404 pPropList->Add(MEDIA_PROPERTY_VIDEO_WIDTH);
405 pPropList->Add(MEDIA_PROPERTY_VIDEO_HEIGHT);
406 pPropList->Add(MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT);
415 _H263Decoder::IsPropertySupported(MediaPropertyType type) const
417 result r = E_SUCCESS;
420 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not constructed");
421 SysTryCatch(NID_MEDIA, (type == MEDIA_PROPERTY_VIDEO_WIDTH || type == MEDIA_PROPERTY_VIDEO_HEIGHT
422 || type == MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT),
423 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
424 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r