Remove deprecated ffurl related code. Use own io_context instead of it
[platform/core/multimedia/libmm-fileinfo.git] / formats / ffmpeg / mm_file_format_frame.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include <stdbool.h>
22 #include <libavformat/avformat.h>
23 #include <libavcodec/avcodec.h>
24 #include <libswscale/swscale.h>
25
26 #include <mm_types.h>
27 #include "mm_file_debug.h"
28 #include "mm_file_formats.h"
29 #include "mm_file_utils.h"
30 #include "mm_file_format_frame.h"
31
32 #define MILLION 1000000
33 #ifdef MMFILE_FORMAT_DEBUG_DUMP
34 static void __save_frame(AVFrame *pFrame, int width, int height, int iFrame);
35
36 void __save_frame(AVFrame *pFrame, int width, int height, int iFrame)
37 {
38         FILE *pFile;
39         char szFilename[32] = {0,};
40         int y = 0;
41         /* Open file */
42
43         memset(szFilename, 0x00, sizeof(szFilename));
44         snprintf(szFilename, sizeof(szFilename), "frame%d.ppm", iFrame);
45         pFile = fopen(szFilename, "wb");
46         if (pFile == NULL)
47                 return;
48
49         /* Write header */
50         fprintf(pFile, "P6\n%d %d\n255\n", width, height);
51         /* Write pixel data */
52         for (y = 0; y < height; y++)
53                 fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile);
54
55         /* Close file */
56         fclose(pFile);
57 }
58 #endif
59
60 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size);
61 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence);
62
63 typedef struct {
64         unsigned char *ptr;
65         long long size;
66         long long offset;
67         int     state;
68 } MMFmemIOHandle;
69
70 static int _mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
71 {
72         MMFmemIOHandle *memHandle = NULL;
73         char **splitedString = NULL;
74
75         filename += strlen(MMFILE_MEM_URI);
76
77         splitedString = mmfile_strsplit(filename, ":");
78         if (splitedString == NULL) {
79                 debug_error(DEBUG, "invalid param\n");
80                 return MMFILE_IO_FAILED;
81         }
82
83         if (!splitedString[0] || !splitedString[1]) {
84                 debug_error(DEBUG, "invalid param\n");
85                 goto exception;
86         }
87
88         memHandle = mmfile_malloc(sizeof(MMFmemIOHandle));
89         if (!memHandle) {
90                 debug_error(DEBUG, "error: mmfile_malloc memHandle\n");
91                 goto exception;
92         }
93
94         memHandle->ptr = (unsigned char *)atoll(splitedString[0]);      /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
95         memHandle->size = atoi(splitedString[1]);
96         memHandle->offset = 0;
97         memHandle->state = 0;
98
99         *handle = memHandle;
100
101         if (splitedString) {
102                 mmfile_strfreev(splitedString);
103         }
104
105         return MMFILE_IO_SUCCESS;
106
107 exception:
108
109         if (splitedString) {
110                 mmfile_strfreev(splitedString);
111         }
112
113         return MMFILE_IO_FAILED;
114 }
115
116 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size)
117 {
118         MMFmemIOHandle *memHandle = NULL;
119         const unsigned char *c = NULL;
120         int len = 0;
121
122         if (!opaque || !buf) {
123                 debug_error(DEBUG, "invalid para\n");
124                 return MMFILE_UTIL_FAIL;
125         }
126
127         memHandle = opaque;
128
129         if (!memHandle->ptr) {
130                 debug_error(DEBUG, "invalid para\n");
131                 return MMFILE_UTIL_FAIL;
132         }
133
134         if (memHandle->offset >= memHandle->size) {
135                 /* for some file formats last file read */
136                 debug_error(DEBUG, "File Read is beyond the file Size\n");
137                 return MMFILE_UTIL_FAIL;
138
139         }
140
141         c = memHandle->ptr + memHandle->offset;
142
143         if (memHandle->state != EOF) {
144                 len = size;
145                 if (len + memHandle->offset > memHandle->size) {
146                         len = memHandle->size - memHandle->offset;
147                 }
148         }
149
150         memcpy(buf, c, len);
151
152         memHandle->offset += len;
153
154         if (memHandle->offset == memHandle->size) {
155                 memHandle->state = EOF;
156         }
157
158         return len;
159 }
160
161 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence)
162 {
163         MMFmemIOHandle *memHandle = NULL;
164         long long tmp_offset = 0;
165
166         if (!opaque) {
167                 debug_error(DEBUG, "invalid para\n");
168                 return MMFILE_UTIL_FAIL;
169         }
170
171         memHandle = opaque;
172
173         switch (whence) {
174                 case SEEK_SET:
175                         tmp_offset = 0 + pos;
176                         break;
177                 case SEEK_CUR:
178                         tmp_offset = memHandle->offset + pos;
179                         break;
180                 case SEEK_END:
181                         tmp_offset = memHandle->size + pos;
182                         break;
183                 case AVSEEK_SIZE:       /*FFMPEG specific*/
184                         return memHandle->size;
185                 default:
186                         return MMFILE_UTIL_FAIL;
187         }
188
189         /*check validation*/
190         if (tmp_offset < 0 && tmp_offset > memHandle->size) {
191                 debug_error(DEBUG, "invalid file offset\n");
192                 return MMFILE_UTIL_FAIL;
193         }
194
195         /*set */
196         memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
197         memHandle->offset = (unsigned int) tmp_offset;
198
199         return tmp_offset;
200 }
201
202 static int __getMimeType(int formatId, char *mimeType, int buf_size)
203 {
204         int ret = 0;    /*default: success*/
205
206         switch (formatId) {
207                 case MM_FILE_FORMAT_3GP:
208                 case MM_FILE_FORMAT_MP4:
209                         snprintf(mimeType, buf_size, "video/3gpp");
210                         break;
211                 case MM_FILE_FORMAT_ASF:
212                 case MM_FILE_FORMAT_WMA:
213                 case MM_FILE_FORMAT_WMV:
214                         snprintf(mimeType, buf_size, "video/x-ms-asf");
215                         break;
216                 case  MM_FILE_FORMAT_AVI:
217                         snprintf(mimeType, buf_size, "video/avi");
218                         break;
219                 case MM_FILE_FORMAT_OGG:
220                         snprintf(mimeType, buf_size, "video/ogg");
221                         break;
222                 case MM_FILE_FORMAT_REAL:
223                         snprintf(mimeType, buf_size, "video/vnd.rn-realmedia");
224                         break;
225                 case MM_FILE_FORMAT_AMR:
226                         snprintf(mimeType, buf_size, "audio/AMR");
227                         break;
228                 case MM_FILE_FORMAT_AAC:
229                         snprintf(mimeType, buf_size, "audio/aac");
230                         break;
231                 case MM_FILE_FORMAT_MP3:
232                         snprintf(mimeType, buf_size, "audio/mp3");
233                         break;
234                 case MM_FILE_FORMAT_AIFF:
235                 case MM_FILE_FORMAT_WAV:
236                         snprintf(mimeType, buf_size, "audio/wave");
237                         break;
238                 case MM_FILE_FORMAT_MID:
239                         snprintf(mimeType, buf_size, "audio/midi");
240                         break;
241                 case MM_FILE_FORMAT_MMF:
242                         snprintf(mimeType, buf_size, "audio/mmf");
243                         break;
244                 case MM_FILE_FORMAT_DIVX:
245                         snprintf(mimeType, buf_size, "video/divx");
246                         break;
247                 case MM_FILE_FORMAT_IMELODY:
248                         snprintf(mimeType, buf_size, "audio/iMelody");
249                         break;
250                 case MM_FILE_FORMAT_JPG:
251                         snprintf(mimeType, buf_size, "image/jpeg");
252                         break;
253                 case MM_FILE_FORMAT_AU:
254                         snprintf(mimeType, buf_size, "audio/basic");
255                         break;
256                 case MM_FILE_FORMAT_VOB:
257                         snprintf(mimeType, buf_size, "video/dvd");
258                         break;
259                 case MM_FILE_FORMAT_FLV:
260                         snprintf(mimeType, buf_size, "video/x-flv");
261                         break;
262                 case MM_FILE_FORMAT_QT:
263                         snprintf(mimeType, buf_size, "video/quicktime");
264                         break;
265                 case MM_FILE_FORMAT_MATROSKA:
266                         snprintf(mimeType, buf_size, "video/x-matroska");
267                         break;
268                 case MM_FILE_FORMAT_FLAC:
269                         snprintf(mimeType, buf_size, "audio/x-flac");
270                         break;
271                 case MM_FILE_FORMAT_M2TS:
272                         snprintf(mimeType, buf_size, "video/MP2T");
273                         break;
274                 case MM_FILE_FORMAT_M2PS:
275                         snprintf(mimeType, buf_size, "video/MP2P");
276                         break;
277                 case MM_FILE_FORMAT_M1VIDEO:
278                         snprintf(mimeType, buf_size, "video/mpeg");
279                         break;
280                 case MM_FILE_FORMAT_M1AUDIO:
281                         snprintf(mimeType, buf_size, "audio/x-mpegaudio");
282                         break;
283                 default:
284                         ret = -1;
285                         break;
286         }
287
288         debug_msg(RELEASE, "id: %d, mimetype: %s\n", formatId, mimeType);
289
290         return ret;
291 }
292
293 extern const struct {
294         int (*Open)(MMFileFormatContext *fileContext);
295         int (*Valid)(MMFileIOHandle *pFileIO, const char *mmfileuri, int mp3FrameCnt);
296 } MMFileFunc[MM_FILE_FORMAT_NUM + 1];
297 static int __get_fileformat(const char *urifilename, int *format)
298 {
299         int index;
300         int ret = 0;
301         MMFileIOHandle *fp = NULL;
302
303         debug_error(DEBUG, "%s\n", urifilename);
304
305         ret = mmfile_open(&fp, urifilename, MMFILE_RDONLY);
306
307         if (ret == MMFILE_IO_FAILED) {
308                 debug_error(DEBUG, "error: mmfile_open\n");
309                 if (fp)
310                         mmfile_close(fp);
311                 return MMFILE_FORMAT_FAIL;
312         }
313
314         for (index = 0; index < MM_FILE_FORMAT_NUM; index++) {
315                 debug_msg(RELEASE, "search index = [%d]\n", index);
316
317                 switch (index) {
318                         case MM_FILE_FORMAT_QT:
319                         case MM_FILE_FORMAT_3GP:
320                         case MM_FILE_FORMAT_MP4:
321                                 *format = MM_FILE_FORMAT_3GP;
322                                 break;
323
324                         case MM_FILE_FORMAT_ASF:
325                         case MM_FILE_FORMAT_WMA:
326                         case MM_FILE_FORMAT_WMV:
327                                 *format = MM_FILE_FORMAT_ASF;
328                                 break;
329
330                         case MM_FILE_FORMAT_DIVX:
331                         case MM_FILE_FORMAT_AVI:
332                                 *format = MM_FILE_FORMAT_AVI;
333                                 break;
334
335                         case MM_FILE_FORMAT_MATROSKA:
336                         case MM_FILE_FORMAT_FLV:
337                         case MM_FILE_FORMAT_M2TS:
338                         case MM_FILE_FORMAT_M2PS:
339                         case MM_FILE_FORMAT_REAL:
340                         case MM_FILE_FORMAT_M1AUDIO:
341                         case MM_FILE_FORMAT_M1VIDEO:
342                                 *format = index;
343                                 break;
344
345                         default: {
346                                 *format = MM_FILE_FORMAT_NUM;
347                                 debug_error(DEBUG, "error: not supported or invaild format enum[%d]\n", index);
348                                 break;
349                         }
350                 }
351
352                 if (MMFileFunc[*format].Valid!= NULL && MMFileFunc[*format].Valid(fp, NULL, 0)) {
353                         goto FILE_FORMAT_SUCCESS;
354                 }
355         }
356
357         if (index == MM_FILE_FORMAT_NUM) {
358                 debug_error(DEBUG, "Can't probe file type\n");
359         }
360
361         *format = -1;
362
363         if (fp)
364                 mmfile_close(fp);
365
366         return MMFILE_FORMAT_FAIL;
367
368 FILE_FORMAT_SUCCESS:
369         if (fp)
370                 mmfile_close(fp);
371
372         return MMFILE_FORMAT_SUCCESS;
373 }
374
375 static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
376 {
377         unsigned int i = 0;
378         int len = 0;
379         int ret = MMFILE_FORMAT_SUCCESS;
380         int videoStream = -1;
381         int key_detected = 0;
382         int got_picture = 0;
383         int64_t pos = timestamp;
384         bool find = false;
385         bool first_seek = true;
386         int64_t pts = 0;
387         AVCodecContext *pVideoCodecCtx = NULL;
388         AVCodec *pVideoCodec = NULL;
389         AVFrame *pFrame = NULL, *pFrameRGB = NULL;
390         AVPacket packet;
391
392         /* Retrieve stream information */
393         if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
394                 debug_error(DEBUG, "error : av_find_stream_info failed");
395                 ret = MMFILE_FORMAT_FAIL;
396                 goto exception; /* Couldn't find stream information */
397         }
398
399         /* Find the first video stream */
400         for (i = 0; i < pFormatCtx->nb_streams; i++) {
401                 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
402                         videoStream = i;
403                         break;
404                 }
405         }
406
407         if (videoStream == -1) {
408                 debug_error(DEBUG, "error : videoStream == -1");
409                 ret = MMFILE_FORMAT_FAIL;
410                 goto exception; /* Didn't find a video stream */
411         }
412
413         /* Get a pointer to the codec context for the video stream */
414         pVideoCodecCtx = pFormatCtx->streams[videoStream]->codec;
415         if (pVideoCodecCtx == NULL) {
416                 debug_error(DEBUG, "invalid param\n");
417                 ret = MMFILE_FORMAT_FAIL;
418                 goto exception;
419         }
420
421         /* Find the decoder for the video stream */
422         pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id);
423         if (pVideoCodec == NULL) {
424                 debug_error(DEBUG, "error : Unsupported codec");
425                 ret = MMFILE_FORMAT_FAIL;
426                 goto exception; /* Codec not found */
427         }
428
429         /* Open codec */
430         pVideoCodecCtx->thread_type = 0;
431         pVideoCodecCtx->thread_count = 0;
432         if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0) {
433                 debug_error(DEBUG, "error : avcodec_open failed");
434                 ret = MMFILE_FORMAT_FAIL;
435                 goto exception;; /*Could not open codec */
436         }
437
438         /* Storing Data  */
439         /* Allocate video frame */
440         pFrame = av_frame_alloc();
441         if (pFrame == NULL) {
442                 debug_error(DEBUG, "error: pFrame is NULL\n");
443                 ret = MMFILE_FORMAT_FAIL;
444                 goto exception;
445         }
446
447         /* Allocate an AVFrame structure */
448         pFrameRGB = av_frame_alloc();
449         if (pFrameRGB == NULL) {
450                 debug_error(DEBUG, "error: pFrameRGB is NULL\n");
451                 ret = MMFILE_FORMAT_FAIL;
452                 goto exception;
453         }
454
455         /* Seeking */
456         AVStream *pStream = pFormatCtx->streams[videoStream];
457         double duration = (double) pFormatCtx->duration / AV_TIME_BASE;
458 #if 0
459         if (duration <= 0) {
460                 double tmpDuration = 0.0;
461
462                 if (pStream->codec->bit_rate > 0 && pFormatCtx->file_size > 0) {
463                         if (pStream->codec->bit_rate >= 8)
464                                 tmpDuration = 0.9 * pFormatCtx->file_size / (pStream->codec->bit_rate / 8);
465
466                         if (tmpDuration > 0)
467                                 duration = tmpDuration;
468                 }
469         }
470 #endif
471         duration = duration * MILLION;
472         if ((duration <= 0) || (duration <= pos)) {
473                 debug_error(DEBUG, "duration error duration[%f] pos[%lld]", duration, pos);
474                 ret = MMFILE_FORMAT_FAIL;
475                 goto exception;
476         }
477
478         if (is_accurate)
479                 av_seek_frame(pFormatCtx, -1, pos, AVSEEK_FLAG_ANY);
480         else
481                 av_seek_frame(pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
482
483         /* Reading Data */
484         int64_t tmpPts = 0;
485 #ifdef __MMFILE_TEST_MODE__
486         int idx = 0;
487 #endif
488
489         av_init_packet(&packet);
490
491         while (av_read_frame(pFormatCtx, &packet) >= 0) {
492                 got_picture = 0;
493
494                 /* Is this a packet from the video stream? */
495                 if (packet.stream_index == videoStream) {
496                         #ifdef __MMFILE_TEST_MODE__
497                         debug_msg(RELEASE, "find Video Stream+++++++[%2d]", idx++);
498                         #endif
499
500                         /* Decode video frame*/
501                         len = avcodec_decode_video2(pVideoCodecCtx, pFrame, &got_picture, &packet);
502                         if (len < 0) {
503                                 debug_warning(DEBUG, "Error while decoding frame");
504                         } else if ((packet.flags & AV_PKT_FLAG_KEY) || (key_detected == 1)) {
505
506                                 key_detected = 0;
507
508                                 if (first_seek || !is_accurate) {
509                                         /* This is first seeking or not accurate mode.
510                                         Sometimes flag is AV_PKT_FLAG_KEY but got_picture is NULL.
511                                         first_seek is used when accurate mode and when time stamp's frame is not key frame.
512                                         Go back to previousto Key frame and decode frame until time stamp's frame*/
513
514                                         if (got_picture) {
515                                                 if (pFrame->key_frame) {
516                                                         debug_msg(RELEASE, "find Video Stream+++++++Find key frame");
517                                                 } else {
518                                                         debug_msg(RELEASE, "find Video Stream+++++++ not key frame");
519                                                 }
520
521                                                 /*eventhough decoded pFrame is not key frame, if packet.flags is AV_PKT_FLAG_KEY then can extract frame*/
522                                                 find = true;
523
524                                         } else {
525                                                 debug_msg(RELEASE, "find Video Stream+++++++Find key but no frame");
526                                                 key_detected = 1;
527                                         }
528                                 }
529                         } else {
530                                 if (is_accurate) {
531                                         if (first_seek) {
532                                                 pts = (packet.pts == (int64_t)AV_NOPTS_VALUE) ? (packet.dts * av_q2d(pStream->time_base)) : packet.pts;
533                                                 first_seek = false;
534
535                                                 av_seek_frame(pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
536                                         } else {
537                                                 tmpPts = (packet.pts == (int64_t)AV_NOPTS_VALUE) ? (packet.dts * av_q2d(pStream->time_base)) : packet.pts;
538                                                 if (pts == tmpPts)
539                                                         find = true;
540                                         }
541                                 }
542                         }
543
544                         if (find && got_picture) {
545                                 break;
546                         }
547                 }
548
549                 /* Free the packet that was allocated by av_read_frame*/
550                 av_free_packet(&packet);
551                 av_init_packet(&packet);
552         }
553
554         /*free pkt after loop breaking*/
555         av_free_packet(&packet);
556
557         /* Did we get a video frame?*/
558         if (got_picture && find) {
559
560                 debug_msg(RELEASE, "Find Frame");
561
562                 /* return frame infromations*/
563                 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
564                         *width = pVideoCodecCtx->coded_width;
565                         *height = pVideoCodecCtx->coded_height;
566                 } else {
567                         *width = pVideoCodecCtx->width;
568                         *height = pVideoCodecCtx->height;
569                 }
570
571                 *size = avpicture_get_size(AV_PIX_FMT_RGB24, *width, *height);
572
573                 if (*size > 0)
574                         *frame = mmfile_malloc(*size);
575
576                 if (NULL == *frame) {
577                         debug_error(DEBUG, "error: avpicture_get_size. [%d]\n", *size);
578                         ret = MMFILE_FORMAT_FAIL;
579                         goto exception;
580                 }
581
582                 debug_msg(RELEASE, "size : %d", *size);
583                 debug_msg(RELEASE, "width : %d", *width);
584                 debug_msg(RELEASE, "height : %d", *height);
585                 debug_msg(RELEASE, "frame : %p", *frame);
586
587                 ret = avpicture_fill((AVPicture *)pFrameRGB, *frame, AV_PIX_FMT_RGB24, *width, *height);
588                 if (ret < 0) {
589                         debug_error(DEBUG, "error: avpicture_fill fail. errcode = 0x%08X\n", ret);
590                         ret = MMFILE_FORMAT_FAIL;
591                         goto exception;
592                 }
593
594                 struct SwsContext *img_convert_ctx = NULL;
595
596                 img_convert_ctx = sws_getContext(*width, *height, pVideoCodecCtx->pix_fmt,
597                                                 *width, *height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
598
599                 if (NULL == img_convert_ctx) {
600                         debug_error(DEBUG, "failed to get img convet ctx\n");
601                         ret = MMFILE_FORMAT_FAIL;
602                         goto exception;
603                 }
604
605                 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize,
606                                         0, *height, pFrameRGB->data, pFrameRGB->linesize);
607                 if (ret < 0) {
608                         debug_error(DEBUG, "failed to convet image\n");
609                         sws_freeContext(img_convert_ctx);
610                         img_convert_ctx = NULL;
611                         ret = MMFILE_FORMAT_FAIL;
612                         goto exception;
613                 }
614
615                 sws_freeContext(img_convert_ctx);
616                 img_convert_ctx = NULL;
617
618 #ifdef MMFILE_FORMAT_DEBUG_DUMP
619                 __save_frame(pFrameRGB, pVideoCodecCtx->width, pVideoCodecCtx->height, (int)(pos / 1000));
620 #endif
621         } else {
622                 debug_error(DEBUG, "Not Found Proper Frame[%d][%d]", got_picture, find);
623                 ret = MMFILE_FORMAT_FAIL;
624                 goto exception;
625         }
626
627         if (pFrame)                     av_free(pFrame);
628         if (pFrameRGB)          av_free(pFrameRGB);
629         if (pVideoCodecCtx)     avcodec_close(pVideoCodecCtx);
630
631         return MMFILE_FORMAT_SUCCESS;
632
633 exception:
634         if (*frame) {
635                 mmfile_free(*frame);
636                 *frame = NULL;
637         }
638         if (pFrame)                     av_free(pFrame);
639         if (pFrameRGB)          av_free(pFrameRGB);
640         if (pVideoCodecCtx)     avcodec_close(pVideoCodecCtx);
641
642         return ret;
643 }
644
645 int mmfile_format_get_frame(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
646 {
647         int ret = MMFILE_FORMAT_SUCCESS;
648         AVFormatContext *pFormatCtx = NULL;
649
650         if (!size || !width || !height) {
651                 return MMFILE_FORMAT_FAIL;
652         }
653
654         av_register_all();
655
656         /* Open video file */
657         if (avformat_open_input(&pFormatCtx, path, NULL, NULL) != 0) {
658                 debug_error(DEBUG, "error : avformat_open_input failed");
659                 return MMFILE_FORMAT_FAIL; /* Couldn't open file */
660         }
661
662         if (!pFormatCtx) {
663                 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.\n");
664                 ret = MMFILE_FORMAT_FAIL;
665                 goto exception;
666         }
667
668         ret = __mmfile_get_frame(pFormatCtx, timestamp, is_accurate, frame, size, width, height);
669
670 exception:
671         /* Close video file */
672         if (pFormatCtx) avformat_close_input(&pFormatCtx);
673
674         return ret;
675 }
676
677 int mmfile_format_get_frame_from_memory(const void *data, unsigned int datasize, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
678 {
679         int ret = MMFILE_FORMAT_SUCCESS;
680         int format = -1;
681         char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0, };
682         char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
683         char tempURIBuffer[MMFILE_URI_MAX_LEN] = {0, };
684         char *urifilename = NULL;
685         AVFormatContext *pFormatCtx = NULL;
686         AVInputFormat *grab_iformat = NULL;
687         AVIOContext              *pIOCtx = NULL;
688         MMFmemIOHandle *handle = NULL;
689         uint8_t *avio_ctx_buffer = NULL;
690
691         if (!size || !width || !height) {
692                 return MMFILE_FORMAT_FAIL;
693         }
694
695         av_register_all();
696
697         snprintf(tempURIBuffer, MMFILE_URI_MAX_LEN,  "%s%u:%u", MMFILE_MEM_URI, (unsigned int)data, datasize);
698         urifilename = mmfile_strdup(tempURIBuffer);
699         if (!urifilename) {
700                 debug_error(DEBUG, "error: uri is NULL\n");
701                 return MMFILE_FORMAT_FAIL;
702         }
703
704         mmfile_register_io_all();
705
706         ret = __get_fileformat(urifilename, &format);
707         if (ret != MMFILE_FORMAT_SUCCESS) {
708                 debug_error(DEBUG, "error: file format is invalid\n");
709                 return MMFILE_FORMAT_FAIL;
710         }
711
712         if (__getMimeType(format, mimeType, MMFILE_MIMETYPE_MAX_LEN) < 0) {
713                 debug_error(DEBUG, "error: Error in MIME Type finding\n");
714                 return MMFILE_FORMAT_FAIL;
715         }
716
717         memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
718
719         ret = mmfile_util_get_ffmpeg_format(mimeType, ffmpegFormatName);
720
721         if (MMFILE_UTIL_SUCCESS != ret) {
722                 debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format\n");
723                 return MMFILE_FORMAT_FAIL;
724         }
725
726         grab_iformat = av_find_input_format(ffmpegFormatName);
727
728         if (NULL == grab_iformat) {
729                 debug_error(DEBUG, "error: cannot find format\n");
730                 ret = MMFILE_FORMAT_FAIL;
731                 goto exception;
732         }
733
734         avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
735         if (avio_ctx_buffer == NULL) {
736                 debug_error(DEBUG, "error: cannot alloc avio_ctx_buffert\n");
737                 ret = MMFILE_FORMAT_FAIL;
738                 goto exception;
739         }
740
741         ret = _mmf_mem_open(&handle, urifilename);
742         if (ret !=MMFILE_IO_SUCCESS) {
743                 debug_warning(DEBUG, "failed to _mmf_mem_open.\n");
744                 av_free(avio_ctx_buffer);
745                 ret = MMFILE_FORMAT_FAIL;
746                 goto exception;
747         }
748
749         pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, _mmf_mem_read, NULL, _mmf_mem_seek);
750         if (pIOCtx == NULL) {
751                 debug_error(DEBUG, "error: cannot alloc io context\n");
752                 av_free(avio_ctx_buffer);
753                 mmfile_free(handle);
754                 ret = MMFILE_FORMAT_FAIL;
755                 goto exception;
756         }
757
758         pFormatCtx = avformat_alloc_context();
759         if (!pFormatCtx) {
760                 debug_warning(DEBUG, "failed to avformat_alloc_context\n");
761                 ret = MMFILE_FORMAT_FAIL;
762                 goto exception;
763         }
764
765         pFormatCtx->pb = pIOCtx;
766
767         ret = avformat_open_input(&pFormatCtx, "", grab_iformat, NULL);
768         if (ret < 0) {
769                 debug_error(DEBUG, "error: cannot open %s %d\n", urifilename, ret);
770                 goto exception;
771         }
772
773         ret = __mmfile_get_frame(pFormatCtx, timestamp, is_accurate, frame, size, width, height);
774
775 exception:
776         /* Close video file */
777         if (pIOCtx) {
778                         av_free(pIOCtx->buffer);
779                         av_free(pIOCtx->opaque);
780                         av_free(pIOCtx);
781         }
782
783         if (pFormatCtx)
784                 avformat_close_input(&pFormatCtx);
785
786         return ret;
787 }