merge with master
[framework/osp/image-core.git] / src / FMedia_BmpEncoder.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 /**
19  * @file   FMedia_BmpEncoder.c
20  * @brief  This file contains the implementation of _BmpEncoder class.
21  *
22  */
23
24 #include <unique_ptr.h>
25 #include <FMediaImageTypes.h>
26 #include <FBaseSysLog.h>
27 #include "FMedia_Ffmpeg.h"
28 #include "FMedia_BmpEncoder.h"
29 #include "FMedia_ImageUtil.h"
30
31 using namespace std;
32 using namespace Tizen::Base;
33
34 namespace Tizen { namespace Media
35 {
36
37
38 _BmpEncoder::_BmpEncoder(void)
39 {
40         __pCodecCtx = null;
41         __pCodec = null;
42         __pixelFormat = MEDIA_PIXEL_FORMAT_NONE;
43         __quality = 90;
44         __width = 0;
45         __height = 0;
46 }
47
48 _BmpEncoder::~_BmpEncoder(void)
49 {
50         if (__pCodecCtx)
51         {
52                 avcodec_flush_buffers(__pCodecCtx);
53                 avcodec_close(__pCodecCtx);
54                 av_free(__pCodecCtx);
55                 __pCodecCtx = null;
56                 __pCodec = null;
57         }
58 }
59
60 result
61 _BmpEncoder::Construct(int width, int height,
62                                            MediaPixelFormat srcPixelFormat,
63                                            MediaPixelFormat& reqPixelFormat,
64                                            int quality)
65 {
66         int res;
67
68         SysTryReturnResult(NID_MEDIA, width >= MIN_WIDTH, E_INVALID_ARG,
69                 "Width (%d) < minimum bmp width (%d)", width, MIN_WIDTH);
70         SysTryReturnResult(NID_MEDIA, height >= MIN_HEIGHT, E_INVALID_ARG,
71                 "Height (%d) < minimum bmp height (%d)", height, MIN_HEIGHT);
72         SysTryReturnResult(NID_MEDIA, quality > 0, E_INVALID_ARG,
73                 "Quality should be greater than 0 (%d)", quality);
74         SysTryReturnResult(NID_MEDIA, quality <= 100, E_INVALID_ARG,
75                 "Quality should be lesser than 100 (%d)", quality);
76
77         // TODO: add BGRA8888 support
78         __width = width;
79         __height = height;
80         __quality = quality;
81         __pixelFormat = MEDIA_PIXEL_FORMAT_BGR888;
82         reqPixelFormat = MEDIA_PIXEL_FORMAT_BGR888;
83         __quality = quality;
84
85         avcodec_register_all();
86
87         __pCodec = avcodec_find_encoder(CODEC_ID_BMP);
88         SysTryReturnResult(NID_MEDIA, __pCodec != null, E_UNSUPPORTED_CODEC, "Failed to find bmp encoder.");
89
90         __pCodecCtx = avcodec_alloc_context3(__pCodec);
91         SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_OUT_OF_MEMORY, "context allocation failed.");
92
93         // Context required for opening BMP encoder.
94         // Specifying output image format
95         __pCodecCtx->pix_fmt = (PixelFormat)_ImageUtil::ToFfmpegPixelFormat(__pixelFormat);
96         // Dimensions of the image
97         __pCodecCtx->height = height;
98         __pCodecCtx->width = width;
99
100         res = avcodec_open2(__pCodecCtx, __pCodec, null);
101         SysTryReturnResult(NID_MEDIA, res >= 0, E_OUT_OF_MEMORY, "codec open failed:%d", res);
102
103         return E_SUCCESS;
104 }
105
106 Tizen::Base::ByteBuffer*
107 _BmpEncoder::EncodeN(const byte* pSrcBuf, int srcLength)
108 {
109         result r = E_SUCCESS;
110         int ret = 0;
111         unique_ptr<AVFrame, _FfmpegDeleter> pVideoFrame(avcodec_alloc_frame(), ffmpegDeleter);
112         unique_ptr<ByteBuffer> pRetBuf(new (std::nothrow) ByteBuffer());
113     unique_ptr<AVPacket, _FfmpegDeleter> pPkt(new (std::nothrow) AVPacket, ffmpegDeleter);
114     int gotOutput;
115
116         // TODO: apply pixel format
117         SysTryReturn(NID_MEDIA, pSrcBuf != null && srcLength > 0, null, E_INVALID_ARG,
118                         "[E_INVALID_ARG] pSrcBuf=0x%x srcLength=%d", pSrcBuf, srcLength);
119
120         SysTryReturn(NID_MEDIA, pVideoFrame.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] avcodec_alloc_frame() failed");
121         SysTryReturn(NID_MEDIA, pRetBuf.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] new ByteBuffer() failed.");
122         SysTryReturn(NID_MEDIA, pPkt.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] new AVPacket failed.");
123
124         // Input buffer is a BGR888, so no need for explicit color conversion
125         // to BGR888.
126
127         // pVideoFrame is the input to encoder.
128         pVideoFrame->data[0] = (uint8_t*)pSrcBuf;
129         pVideoFrame->data[1] = 0;
130         pVideoFrame->data[2] = 0;
131         pVideoFrame->data[3] = 0;
132         pVideoFrame->linesize[0] = (__width) * BYTES_PER_PIXEL_RGB;
133         pVideoFrame->linesize[1] = 0;
134         pVideoFrame->linesize[2] = 0;
135         pVideoFrame->linesize[3] = 0;
136
137         av_init_packet(pPkt.get());
138         pPkt->data = NULL;    // packet data will be allocated by the encoder
139         pPkt->size = 0;
140         gotOutput = 0;
141
142         ret = avcodec_encode_video2(__pCodecCtx, pPkt.get(), pVideoFrame.get(), &gotOutput);
143         SysTryReturn(NID_MEDIA, ret >= 0 && gotOutput > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Encode Failed:%d %d", ret, gotOutput);
144
145         r = pRetBuf->Construct(pPkt->size);
146         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ByteBuffer.Construct(%d) failed", GetErrorMessage(r), pPkt->size);
147
148         r = pRetBuf->SetArray(pPkt->data, 0, pPkt->size);
149         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ByteBuffer.SetArray(%x, 0, %d) failed",
150                 GetErrorMessage(r), pPkt->data, pPkt->size);
151         pRetBuf->Flip();
152
153         return pRetBuf.release();
154 }
155
156 result
157 _BmpEncoder::SetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
158 {
159         return E_UNSUPPORTED_OPERATION;
160 }
161
162 }} // Tizen::Media