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 * @file FMedia_BmpDecoder.c
20 * @brief This file contains the implementation of _BmpDecoder class.
22 #include <unique_ptr.h>
23 #include <FBaseSysLog.h>
24 #include <FMediaImageTypes.h>
25 #include "FMedia_Ffmpeg.h"
26 #include "FMedia_BmpDecoder.h"
27 #include "FMedia_ImageUtil.h"
29 using namespace Tizen::Io;
30 using namespace Tizen::Base::Collection;
32 namespace Tizen { namespace Media
35 static const int _INPUT_BUFFER_PADDING_SIZE = FF_INPUT_BUFFER_PADDING_SIZE;
37 _BmpDecoder::_BmpDecoder(void)
43 , __pixelFormat(MEDIA_PIXEL_FORMAT_NONE)
47 _BmpDecoder::~_BmpDecoder(void)
51 avcodec_flush_buffers(__pCodecCtx);
52 avcodec_close(__pCodecCtx);
58 av_free(__pVideoFrame);
63 _BmpDecoder::OpenCodec(void)
68 avcodec_register_all();
70 __pCodec = avcodec_find_decoder(CODEC_ID_BMP);
71 SysTryReturnResult(NID_MEDIA, __pCodec != null, E_UNSUPPORTED_CODEC, "Failed to find bmp decoder.");
73 __pCodecCtx = avcodec_alloc_context3(__pCodec);
74 SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_OUT_OF_MEMORY, "context allocation failed.");
76 res = avcodec_open2(__pCodecCtx, __pCodec, null);
77 SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM,
78 "[E_SYSTEM] Failed to open bmp decoder.");
80 // AVCodecContext parameters
81 if (__pCodec->capabilities & CODEC_CAP_TRUNCATED)
83 __pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
86 // Allocate memory for decoder output.
87 __pVideoFrame = avcodec_alloc_frame();
88 SysTryCatch(NID_MEDIA, __pVideoFrame != null, r = E_OUT_OF_MEMORY,
89 E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Output buffer allocation failed");
100 _BmpDecoder::CloseCodec(void)
104 avcodec_close(__pCodecCtx);
105 av_free(__pCodecCtx);
110 //__inputPacket.size = 0;
111 //SAFE_DELETE_ARRAY(__inputPacket.data);
115 _BmpDecoder::Construct(const byte* buffer, int length, MediaPixelFormat pixelFormat)
117 result r = E_SUCCESS;
118 // uint8_t* pInputData = null;
123 SysTryCatch(NID_MEDIA, buffer != null, r = E_INVALID_ARG, E_INVALID_ARG,
124 "[E_INVALID_ARG] buffer is null.");
126 SysTryCatch(NID_MEDIA, length > 0, r = E_INVALID_ARG, E_INVALID_ARG,
127 "[E_INVALID_ARG] length is zero.");
129 // _TRY_CATCH_INVALID_STATE(!__pCodecCtx);
130 SysTryCatch(NID_MEDIA, !__pCodecCtx, r = E_INVALID_STATE, E_INVALID_STATE,
131 "[E_INVALID_STATE] Already Constructed");
133 // Initialize ffmpeg.
135 SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = E_SYSTEM, E_SYSTEM,
136 "[E_SYSTEM] Could not initialize FFMPEG.");
138 // Forming the input packet for decoder.
139 av_init_packet(&pkt);
140 // Decoder input must end in a padding of 8 zeroes.
141 pkt.size = length + _INPUT_BUFFER_PADDING_SIZE;
142 __pSrcBuf.reset(new (std::nothrow) byte[pkt.size]);
143 SysTryCatch(NID_MEDIA, __pSrcBuf.get() != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
144 "[E_OUT_OF_MEMORY] Could not allocate %d bytes for input frame.", pkt.size);
145 memcpy(__pSrcBuf.get(), buffer, length);
146 memset(__pSrcBuf.get() + length, 0, _INPUT_BUFFER_PADDING_SIZE);
147 pkt.data = (uint8_t*)__pSrcBuf.get();
150 // Decoding has been done in Construct instead of in DecodeN
151 // function because GetDimension is called in the _ImageDecoderImpl
152 // function, before decode. Since dimensions are not available
153 // till the image is decoded, decode is done here.
154 // If "avcodec_decode_video2" must be moved to "DecodeN",
155 // then the sequence of calls in _ImageDecoderImpl should be changed.
158 res = avcodec_decode_video2(__pCodecCtx, __pVideoFrame, &gotPicture, &pkt);
159 // avcodec_decode_video2 returns res greater than zero on success.
160 SysTryCatch(NID_MEDIA, res > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Decode Failed");
161 // The value of gotPicture is non zero if a frame is found.
162 SysTryCatch(NID_MEDIA, gotPicture, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Decode Failed");
164 // Dimensions are __pCodecCtx->width and __pCodecCtx->height.
173 _BmpDecoder::DecodeN(int& outLength)
177 std::unique_ptr<byte[]> pOutBuf;
179 SysTryReturn(NID_MEDIA, __pCodecCtx, null, E_INVALID_STATE,
180 "[E_INVALID_STATE] Not Constructed");
182 // The following steps convert the decoder output to RGB565LE
183 // format, irrespective of decoder output format.
184 // Also required to eliminate the "padding" present in decoder
187 outLength = avpicture_get_size(__pCodecCtx->pix_fmt, __pCodecCtx->width,
188 __pCodecCtx->height);
189 SysTryReturn(NID_MEDIA, 0 < outLength, null, E_OUT_OF_MEMORY, "FFMPEG returned buffer size as zero.");
191 pOutBuf.reset(new (std::nothrow) byte[outLength]);
192 SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
193 "[E_OUT_OF_MEMORY] Memory allocation of %d bytes for output buffer failed!", outLength);
194 __pixelFormat = _ImageUtil::ToMediaPixelFormatFromFfmpeg(__pCodecCtx->pix_fmt);
196 resFfmpeg = av_image_copy_to_buffer(pOutBuf.get(), outLength,
197 (const uint8_t * const*)__pVideoFrame->data, (const int*)__pVideoFrame->linesize,
198 __pCodecCtx->pix_fmt, __pCodecCtx->width, __pCodecCtx->height, 1);
200 SysTryReturn(NID_MEDIA, resFfmpeg >= 0, null, E_SYSTEM,
201 "[E_SYSTEM] Could not copy image data to buffer!!");
203 SetLastResult(E_SUCCESS);
204 return pOutBuf.release();
208 _BmpDecoder::SetDecodingRegion(int x, int y, int width, int height)
210 // result r = E_SUCCESS;
212 // SysTryCatch(NID_MEDIA, __isConstructed, r = E_INVALID_STATE,
213 // E_INVALID_STATE, "[E_INVALID_STATE] Instance is not constructed.");
217 return E_UNSUPPORTED_OPERATION;
221 _BmpDecoder::GetDimension(int& width, int& height)
223 SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not Constructed.");
225 SysTryReturnResult(NID_MEDIA, __pCodecCtx->width > 0 && __pCodecCtx->height > 0, E_INVALID_STATE,
226 "Invalid dimensions : (%d x %d)", __pCodecCtx->width, __pCodecCtx->height);
228 width = __pCodecCtx->width;
229 height = __pCodecCtx->height;
235 _BmpDecoder::GetPixelFormat(void)
237 MediaPixelFormat pixel_format = MEDIA_PIXEL_FORMAT_NONE;
239 SysTryReturn(NID_MEDIA, __pCodecCtx, pixel_format, E_INVALID_STATE,
240 "[E_INVALID_STATE] Not constructed");
242 return __pixelFormat;
246 _BmpDecoder::SetScaleDown(int scaleDown)
248 result r = E_SUCCESS;
250 SysTryReturn(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, E_INVALID_STATE,
251 "[E_INVALID_STATE] Not Constructed.");
257 _BmpDecoder::GetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
259 return E_UNSUPPORTED_OPERATION;