Tizen 2.0 Release
[framework/osp/media.git] / src / FMedia_VideoFrameExtractorImpl.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_VideoFrameExtractorImpl.cpp
20  * @brief  This file contains the implementation of VideoFrameExtractor's impl layer.
21  */
22
23 #include <memory>
24 #include <unique_ptr.h>
25 #include <FMediaImageUtil.h>
26 #include <FBaseSysLog.h>
27 #include <metadata_extractor.h>
28 #include "FMedia_VideoFrameExtractorImpl.h"
29 #include "FMedia_ColorConverter.h"
30 #include <FIo.h>
31
32 using namespace Tizen::Base;
33 using namespace Tizen::Graphics;
34
35 namespace Tizen { namespace Media {
36
37 _VideoFrameExtractorImpl::_VideoFrameExtractorImpl(void)
38         : __extractor(null)
39         , __pixelFormat(MEDIA_PIXEL_FORMAT_NONE)
40         , __width(0)
41         , __height(0)
42         , __duration(0)
43 {
44 }
45
46 _VideoFrameExtractorImpl::~_VideoFrameExtractorImpl(void)
47 {
48         if (__extractor != null)
49         {
50                 metadata_extractor_destroy(__extractor);
51                 __extractor = null;
52         }
53 }
54
55
56 _VideoFrameExtractorImpl*
57 _VideoFrameExtractorImpl::GetInstance(VideoFrameExtractor *pVideoFrameExtractor)
58 {
59         if (pVideoFrameExtractor != null)
60         {
61                 return pVideoFrameExtractor->__pImpl;
62         }
63         return null;
64 }
65
66 const _VideoFrameExtractorImpl*
67 _VideoFrameExtractorImpl::GetInstance(const VideoFrameExtractor *pVideoFrameExtractor)
68 {
69         if (pVideoFrameExtractor != null)
70         {
71                 return pVideoFrameExtractor->__pImpl;
72         }
73         return null;
74 }
75
76 result
77 _VideoFrameExtractorImpl::Construct(const Tizen::Base::String &filePath, MediaPixelFormat pixelFormat)
78 {
79         result r = E_SUCCESS;
80         int ret = 0;
81         std::unique_ptr<char[]> pPath;
82         int length = 0;
83
84         SysAssertf(__extractor == null,
85                         "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class.");
86
87         ret = metadata_extractor_create(&__extractor);
88         TryCatch(ret == METADATA_EXTRACTOR_ERROR_NONE, r = ToResult(ret), "metadata_extractor_create:%d", ret);
89
90         SysTryReturn(NID_MEDIA, !filePath.IsEmpty(), E_FILE_NOT_FOUND, E_FILE_NOT_FOUND,
91                         "[E_FILE_NOT_FOUND] path is empty");
92
93         SysTryReturn(NID_MEDIA, Tizen::Io::File::IsFileExist(filePath), E_FILE_NOT_FOUND, E_FILE_NOT_FOUND,
94                         "[E_FILE_NOT_FOUND] File is not Found: %ls",filePath.GetPointer());
95
96         SysTryReturn(NID_MEDIA, pixelFormat > MEDIA_PIXEL_FORMAT_NONE && pixelFormat < MEDIA_PIXEL_FORMAT_GRAY,
97                 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Pixel format (%d) is invalid.", pixelFormat);
98
99         __pixelFormat = pixelFormat;
100
101         length = filePath.GetLength();
102         pPath.reset(new (std::nothrow) char[length + 2]);
103
104         SysTryReturn(NID_MEDIA, pPath.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
105                 "[%s] Propagating. ", GetErrorMessage(GetLastResult()));
106
107         snprintf(pPath.get(), length+2, "%ls", filePath.GetPointer());
108
109         ret = metadata_extractor_set_path(__extractor, pPath.get());
110         TryCatch(ret == METADATA_EXTRACTOR_ERROR_NONE, r = ToResult(ret), "metadata_extractor_set_path:%d", ret);
111
112         r = GetMetaDataValue(__extractor, METADATA_VIDEO_WIDTH, __width);
113         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
114
115         r = GetMetaDataValue(__extractor, METADATA_VIDEO_HEIGHT, __height);
116         TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
117
118         {
119                 int val = 0;
120                 r = GetMetaDataValue(__extractor, METADATA_DURATION, val);
121                 TryCatch(r == E_SUCCESS, , "[%s] Propagating.", GetErrorMessage(r));
122                 __duration = val;
123         }
124
125 CATCH:
126         return r;
127 }
128
129 int
130 _VideoFrameExtractorImpl::GetWidth(void) const
131 {
132         return __width;
133 }
134
135 int
136 _VideoFrameExtractorImpl::GetHeight(void) const
137 {
138         return __height;
139 }
140
141 long
142 _VideoFrameExtractorImpl::GetDuration(void) const
143 {
144         return __duration;
145 }
146
147 ImageBuffer*
148 _VideoFrameExtractorImpl::GetFrameN(long timestamp)
149 {
150         result r = E_SUCCESS;
151         int ret = 0;
152         void* pFrame = null;
153         int frameSize = 0;
154         std::unique_ptr <byte[]> pBuf;
155         int bufLength = 0;
156         ByteBuffer srcBuf;
157         ByteBuffer dstBuf;
158         ImageBuffer* pImgBuf = null;
159         _ColorConverter cvt;
160
161         TryCatch(timestamp < __duration, r = E_OUT_OF_RANGE,
162                         "[%s] Propagating.",GetErrorMessage(E_OUT_OF_RANGE));
163
164         ret = metadata_extractor_get_frame_at_time(__extractor, timestamp, false, &pFrame, &frameSize );
165
166         TryCatch(ret == METADATA_EXTRACTOR_ERROR_NONE, r = ToResult(ret),
167                         "[%s] Propagating.",GetErrorMessage(ToResult(ret)));
168
169         TryCatch(pFrame != null && frameSize > 0, r = E_OPERATION_FAILED,
170                         "[%s] Propagating.",GetErrorMessage(E_OPERATION_FAILED));
171
172         pImgBuf = new (std::nothrow) ImageBuffer();
173         TryCatch(pImgBuf != null, r = E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
174
175         r = cvt.Construct(MEDIA_PIXEL_FORMAT_RGB888, __width, __height, __pixelFormat, __width, __height);
176         TryCatch(r == E_SUCCESS, delete pImgBuf; pImgBuf = null, "[%s] Color conversion failed.", GetErrorMessage(r));
177
178         pBuf.reset(cvt.ConvertN((byte*)pFrame, frameSize, bufLength));
179         r = GetLastResult();
180         TryCatch((r == E_SUCCESS) && (pBuf.get() != null) && (bufLength > 0), delete pImgBuf; pImgBuf = null,
181                 "[%s] Color conversion failed.", GetErrorMessage(r));
182
183         r = pImgBuf->Construct(__width, __height, __pixelFormat, pBuf.get(), bufLength);
184         TryCatch(r == E_SUCCESS, delete pImgBuf; pImgBuf = null,
185                 "[%s] Color conversion failed.", GetErrorMessage(r));
186
187         r = E_SUCCESS;
188
189 CATCH:
190         if (pFrame != null)
191         {
192                 free(pFrame);
193                 pFrame = null;
194         }
195         SetLastResult(r);
196         return pImgBuf;
197 }
198
199 ImageBuffer*
200 _VideoFrameExtractorImpl::GetFrameN(const Tizen::Base::String& filePath, MediaPixelFormat pixelFormat, long timestamp)
201 {
202         result r = E_SUCCESS;
203         ImageBuffer* pImgBuf = null;
204
205         std::unique_ptr <_VideoFrameExtractorImpl> pImpl(new _VideoFrameExtractorImpl());
206         TryCatch(pImpl.get() != null, r = E_OUT_OF_MEMORY,
207                 "[%s] Propagating. ", GetErrorMessage(GetLastResult()));
208
209         r = (pImpl.get())->Construct(filePath, pixelFormat);
210         TryCatch(r == E_SUCCESS, , "[%s] Failed to  Construct pImpl", GetErrorMessage(r));
211
212         pImgBuf = (pImpl.get())->GetFrameN(timestamp);
213         TryCatch(pImgBuf != null, r = GetLastResult(), "[%s] Propagating", GetErrorMessage(r));
214
215 CATCH:
216         SetLastResult(r);
217         return pImgBuf;
218 }
219
220 result
221 _VideoFrameExtractorImpl::ToResult(int ret)
222 {
223         static struct
224         {
225                 int slpError;
226                 result ospError;
227         } errorMap[] = {
228                 { METADATA_EXTRACTOR_ERROR_NONE, E_SUCCESS },
229                 { METADATA_EXTRACTOR_ERROR_INVALID_PARAMETER, E_INVALID_ARG },
230                 { METADATA_EXTRACTOR_ERROR_OUT_OF_MEMORY, E_OUT_OF_MEMORY },
231                 { METADATA_EXTRACTOR_ERROR_FILE_EXISTS, E_FILE_NOT_FOUND },
232                 { METADATA_EXTRACTOR_ERROR_OPERATION_FAILED, E_UNSUPPORTED_FORMAT },
233         };
234
235         for (unsigned int index = 0; index < sizeof(errorMap) / sizeof(errorMap[0]); index++)
236         {
237                 if (errorMap[index].slpError == ret)
238                 {
239                         return errorMap[index].ospError;
240                 }
241         }
242
243         return E_UNKNOWN;
244 }
245
246 result
247 _VideoFrameExtractorImpl::GetMetaDataValue(struct metadata_extractor_s*& extractor,int key, int &value)
248 {
249         char* pOutStr = null;
250         result r = E_SUCCESS;
251         int ret = -1;
252
253         ret = metadata_extractor_get_metadata(extractor, (metadata_extractor_attr_e)key, &pOutStr);
254         TryCatch(ret == METADATA_EXTRACTOR_ERROR_NONE, r = ToResult(ret), "[%s] Propagating .", GetErrorMessage(ToResult(ret)));
255
256         value = atoi(pOutStr);
257         free(pOutStr);
258         pOutStr = null;
259
260 CATCH:
261         return r;
262 }
263
264 }} // Tizen::Media
265