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 avcodec_register_all();
69 __pCodecCtx = avcodec_alloc_context();
70 SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM,
71 "[%s] AVCODEC Context Allcoation Failed",GetErrorMessage(E_SYSTEM));
\r
72 __pCodec = avcodec_find_decoder(CODEC_ID_H263);
73 SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM,
74 "[%s] AVCODEC Find Decoder Failed for CODEC_ID_H263",GetErrorMessage(E_SYSTEM));
\r
76 res = avcodec_open(__pCodecCtx, __pCodec);
77 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
78 "[%s] AVCODEC Codec Open Failed for CODEC_ID_H263",GetErrorMessage(E_SYSTEM));
\r
80 // AVCodecContext parameters
81 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
83 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
86 __pCodecCtx->debug_mv = 0; //set by user
87 __pCodecCtx->debug = 0; //set by user
88 __pCodecCtx->workaround_bugs = 1; //set by user
89 __pCodecCtx->lowres = 0; //set by user
90 __pCodecCtx->skip_frame = AVDISCARD_DEFAULT; //set by user
91 __pCodecCtx->skip_idct = AVDISCARD_DEFAULT; //set by user
92 __pCodecCtx->skip_loop_filter = AVDISCARD_DEFAULT; //set by user
97 if (__pCodecCtx != null)
99 avcodec_close(__pCodecCtx);
107 _H263Decoder::Decode(const byte* pSrcBuf, int& srcBufLength,
108 byte*& pDstBuf, int& dstBufLength, bool& gotFrame)
110 result r = E_SUCCESS;
112 AVFrame* pVideoFrame = null;
113 AVPacket inputPacket;
115 int remainingBytes = 0;
120 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
121 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && pDstBuf != null && srcBufLength > 0 && dstBufLength > 0),
122 E_INVALID_ARG, "Invalid argument is used. The argument is not valid");
\r
124 av_init_packet(&inputPacket);
125 inputPacket.size = srcBufLength;
126 pVideoFrame = avcodec_alloc_frame();
127 SysTryCatch(NID_MEDIA, pVideoFrame != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
128 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
130 inputPacket.data = (uint8_t*) pSrcBuf;
131 // Decoding the video packet
132 remainingBytes = srcBufLength;
136 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
137 SysTryCatch(NID_MEDIA, res >= 0, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
138 "[%s] The input data format is not supported ", GetErrorMessage(E_UNSUPPORTED_FORMAT));
\r
140 remainingBytes -= res;
141 inputPacket.data += res;
142 inputPacket.size -= res;
146 __isDecodeCalled = true;
147 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
149 SysTryCatch(NID_MEDIA, dstBufLength >= (__pCodecCtx->height*__pCodecCtx->width*3)/2,
150 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
151 "[%s] pDstBuf:%d %d %d",GetErrorMessage(E_OUT_OF_MEMORY),
\r
152 dstBufLength, __pCodecCtx->height, __pCodecCtx->width);
153 for (i = 0; i < __pCodecCtx->height; i++)
155 srcOffset = i * pVideoFrame->linesize[0];
156 offset = i * __pCodecCtx->width;
157 memcpy(pDstBuf + offset, pVideoFrame->data[0] + srcOffset, __pCodecCtx->width);
159 for (i = 0; i < __pCodecCtx->height / 2; i++)
161 srcOffset = i * pVideoFrame->linesize[1];
162 offset = (__pCodecCtx->height * __pCodecCtx->width) + (i * __pCodecCtx->width) / 2;
163 memcpy(pDstBuf + offset, pVideoFrame->data[1] + srcOffset, __pCodecCtx->width / 2);
165 for (i = 0; i < __pCodecCtx->height / 2; i++)
167 srcOffset = i * pVideoFrame->linesize[2];
168 offset = ((__pCodecCtx->height * __pCodecCtx->width * 5) / 4) + (i * __pCodecCtx->width) / 2;
169 memcpy(pDstBuf + offset, pVideoFrame->data[2] + srcOffset, __pCodecCtx->width / 2);
172 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
173 dstBufLength = (__pCodecCtx->height * __pCodecCtx->width * 3) / 2;
178 while (remainingBytes);
182 // "Trying for another decode"
183 inputPacket.data = null;
184 inputPacket.size = 0;
185 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
189 __isDecodeCalled = true;
190 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P ) // handling only yuv 420 case
192 SysTryCatch(NID_MEDIA, dstBufLength >= (__pCodecCtx->height*__pCodecCtx->width*3)/2,
193 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
194 "[%s] Decode Failed Insufficient destination buffer",GetErrorMessage(E_OUT_OF_MEMORY));
\r
195 for (i = 0; i < __pCodecCtx->height; i++)
197 srcOffset = i * pVideoFrame->linesize[0];
198 offset = i * __pCodecCtx->width;
199 memcpy(pDstBuf + offset, pVideoFrame->data[0] + srcOffset, __pCodecCtx->width);
201 for (i = 0; i < __pCodecCtx->height / 2; i++)
203 srcOffset = i * pVideoFrame->linesize[1];
204 offset = (__pCodecCtx->height * __pCodecCtx->width) + (i * __pCodecCtx->width) / 2;
205 memcpy(pDstBuf + offset, pVideoFrame->data[1] + srcOffset, __pCodecCtx->width / 2);
207 for (i = 0; i < __pCodecCtx->height / 2; i++)
209 srcOffset = i * pVideoFrame->linesize[2];
210 offset = ((__pCodecCtx->height * __pCodecCtx->width * 5) / 4) + (i * __pCodecCtx->width) / 2;
211 memcpy(pDstBuf + offset, pVideoFrame->data[2] + srcOffset, __pCodecCtx->width / 2);
214 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
215 dstBufLength = (__pCodecCtx->height * __pCodecCtx->width * 3) / 2;
221 srcBufLength = srcBufLength - remainingBytes; //Input bytes used
226 av_free(pVideoFrame);
231 if (pVideoFrame != null)
233 av_free(pVideoFrame);
236 SysLog(NID_MEDIA, "Error is %d.", res);
241 _H263Decoder::Probe(const byte* pSrcBuf, const int srcBufLength, int& width, int& height,
242 MediaPixelFormat& pixelFormat)
244 result r = E_SUCCESS;
246 AVFrame* pVideoFrame = null;
247 AVPacket inputPacket;
249 int remainingBytes = 0;
251 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
252 SysTryReturnResult(NID_MEDIA, (pSrcBuf != null && srcBufLength > 0), E_INVALID_ARG,
253 "Invalid argument is used. The argument is not valid");
\r
255 av_init_packet(&inputPacket);
256 inputPacket.size = srcBufLength + FF_INPUT_BUFFER_PADDING_SIZE;
257 pVideoFrame = avcodec_alloc_frame();
259 SysTryCatch(NID_MEDIA, (pVideoFrame != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
260 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
261 inputPacket.data = (uint8_t*) pSrcBuf;
263 // Decoding the video packet
264 remainingBytes = inputPacket.size;
268 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
269 SysTryCatch(NID_MEDIA, res >= 0, r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
270 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
275 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
277 width = __pCodecCtx->width;
278 height = __pCodecCtx->height;
279 pixelFormat = MEDIA_PIXEL_FORMAT_YUV420P;
284 remainingBytes -= res;
285 inputPacket.data += res;
286 inputPacket.size -= res;
288 while (remainingBytes);
292 inputPacket.data = null;
293 inputPacket.size = 0;
294 res = avcodec_decode_video2(__pCodecCtx, pVideoFrame, &gotPicture, &inputPacket);
295 if (gotPicture && res >= 0)
298 if (__pCodecCtx->pix_fmt == PIX_FMT_YUV420P) // handling only yuv 420 case
300 width = __pCodecCtx->width;
301 height = __pCodecCtx->height;
302 pixelFormat = MEDIA_PIXEL_FORMAT_YUV420P;
307 r = E_UNSUPPORTED_FORMAT;
311 if (pVideoFrame != null)
313 av_free(pVideoFrame);
318 if (pVideoFrame != null)
320 av_free(pVideoFrame);
326 _H263Decoder::Reset(void)
328 result r = E_SUCCESS;
330 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
331 avcodec_flush_buffers(__pCodecCtx);
332 __isDecodeCalled = false;
338 _H263Decoder::GetValue(MediaPropertyType type, int& value) const
340 result r = E_SUCCESS;
342 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "The instance is in invalid state");
\r
343 SysTryCatch(NID_MEDIA, __isDecodeCalled == true, r = E_INVALID_STATE, E_INVALID_STATE,
344 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
345 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
346 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
347 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH && type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
348 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
349 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r
353 case MEDIA_PROPERTY_VIDEO_WIDTH:
354 value = __pCodecCtx->width;
357 case MEDIA_PROPERTY_VIDEO_HEIGHT:
358 value = __pCodecCtx->height;
361 case MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT:
362 value = MEDIA_PIXEL_FORMAT_YUV420P;
366 return E_OBJ_NOT_FOUND;
376 _H263Decoder::GetValue(MediaPropertyType type, float& value) const
378 result r = E_SUCCESS;
380 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not constructed");
381 SysTryCatch(NID_MEDIA, __isDecodeCalled == true, r = E_INVALID_STATE, E_INVALID_STATE,
382 "[%s] The instance is in invalid state",GetErrorMessage(E_INVALID_STATE));
\r
383 SysTryCatch(NID_MEDIA, type > 0, r = E_INVALID_ARG, E_INVALID_ARG,
384 "[%s] Invalid argument is used. The argument is not valid",GetErrorMessage(E_INVALID_ARG));
\r
385 SysTryCatch(NID_MEDIA, type >= MEDIA_PROPERTY_VIDEO_WIDTH || type <= MEDIA_PROPERTY_AUDIO_SAMPLE_RATE,
386 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r
388 return E_OBJ_NOT_FOUND;
394 Tizen::Base::Collection::IListT<MediaPropertyType>*
395 _H263Decoder::GetSupportedPropertyListN(void) const
397 result r = E_SUCCESS;
399 ArrayListT<MediaPropertyType>* pPropList = new (std::nothrow) ArrayListT<MediaPropertyType>;
400 SysTryCatch(NID_MEDIA, pPropList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
401 "[%s] Memory Allocation Failed ",GetErrorMessage(E_OUT_OF_MEMORY));
\r
402 pPropList->Add(MEDIA_PROPERTY_VIDEO_WIDTH);
403 pPropList->Add(MEDIA_PROPERTY_VIDEO_HEIGHT);
404 pPropList->Add(MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT);
413 _H263Decoder::IsPropertySupported(MediaPropertyType type) const
415 result r = E_SUCCESS;
418 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not constructed");
419 SysTryCatch(NID_MEDIA, (type == MEDIA_PROPERTY_VIDEO_WIDTH || type == MEDIA_PROPERTY_VIDEO_HEIGHT
420 || type == MEDIA_PROPERTY_VIDEO_PIXEL_FORMAT),
421 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
422 "[%s] The instance is not available ",GetErrorMessage(E_OBJ_NOT_FOUND));
\r