4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Haejeong Kim <backto.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include <libavformat/avformat.h>
26 #include <libavcodec/avcodec.h>
27 #ifdef __MMFILE_FFMPEG_V085__
28 #include <libswscale/swscale.h>
33 #include "mm_file_formats.h"
34 #include "mm_file_utils.h"
35 #include "mm_file_format_ffmpeg.h"
37 #include "mm_file_format_ffmpeg_mem.h"
40 #define _SHORT_MEDIA_LIMIT 2000 /* under X seconds duration*/
42 extern int img_convert (AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt,int src_width, int src_height);
44 /* internal functions */
45 static int _is_good_pgm (unsigned char *buf, int wrap, int xsize, int ysize);
46 #ifdef MMFILE_FORMAT_DEBUG_DUMP
47 static void _save_pgm (unsigned char *buf, int wrap, int xsize, int ysize, char *filename);
49 #ifdef __MMFILE_TEST_MODE__
50 static void _dump_av_packet (AVPacket *pkt);
53 static int _get_video_fps (int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup);
54 static int _get_first_good_video_frame (AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame);
56 static int ConvertVideoCodecEnum (int AVVideoCodecID);
57 static int ConvertAudioCodecEnum (int AVAudioCodecID);
59 /* plugin manadatory API */
60 int mmfile_format_read_stream_ffmpg (MMFileFormatContext * formatContext);
61 int mmfile_format_read_frame_ffmpg (MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
62 int mmfile_format_read_tag_ffmpg (MMFileFormatContext *formatContext);
63 int mmfile_format_close_ffmpg (MMFileFormatContext *formatContext);
64 static int getMimeType(int formatId, char *mimeType);
69 int mmfile_format_open_ffmpg (MMFileFormatContext *formatContext)
71 AVFormatContext *pFormatCtx = NULL;
72 AVInputFormat *grab_iformat = NULL;
75 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0,};
76 char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0,};
78 formatContext->ReadStream = mmfile_format_read_stream_ffmpg;
79 formatContext->ReadFrame = mmfile_format_read_frame_ffmpg;
80 formatContext->ReadTag = mmfile_format_read_tag_ffmpg;
81 formatContext->Close = mmfile_format_close_ffmpg;
83 #ifdef __MMFILE_TEST_MODE__
84 debug_msg ("ffmpeg version: %d\n", avformat_version ());
95 av_log_set_level (AV_LOG_DEBUG);
97 av_log_set_level (AV_LOG_QUIET);
102 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
104 #if (defined __MMFILE_FFMPEG_V085__ && ! defined __MMFILE_LIBAV_VERSION__)
105 ffurl_register_protocol(&MMFileMEMProtocol, sizeof (URLProtocol));
107 register_protocol (&MMFileMEMProtocol);
109 if(getMimeType(formatContext->filesrc->memory.format,mimeType)< 0) {
110 debug_error ("error: Error in MIME Type finding\n");
111 return MMFILE_FORMAT_FAIL;
114 memset (ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
116 ret = mmfile_util_get_ffmpeg_format (mimeType,ffmpegFormatName);
118 if (MMFILE_UTIL_SUCCESS != ret) {
119 debug_error ("error: mmfile_util_get_ffmpeg_format\n");
120 return MMFILE_FORMAT_FAIL;
123 grab_iformat = av_find_input_format (ffmpegFormatName);
125 if (NULL == grab_iformat) {
126 debug_error ("error: cannot find format\n");
130 #ifdef __MMFILE_FFMPEG_V085__
131 ret = avformat_open_input (&pFormatCtx, formatContext->uriFileName, grab_iformat, NULL);
133 ret = av_open_input_file (&pFormatCtx, formatContext->uriFileName, grab_iformat, 0, NULL);
136 debug_error("error: cannot open %s %d\n", formatContext->uriFileName, ret);
139 formatContext->privateFormatData = pFormatCtx;
142 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
144 if (formatContext->isdrm == MM_FILE_DRM_OMA) {
145 debug_error ("error: drm content\n");
149 #ifdef __MMFILE_FFMPEG_V085__
150 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
152 ret = av_open_input_file(&pFormatCtx, formatContext->filesrc->file.path, NULL, 0, NULL);
155 debug_error("error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
158 formatContext->privateFormatData = pFormatCtx;
162 if (!pFormatCtx || !(pFormatCtx->nb_streams > 0)) {
163 debug_warning ("failed to find av stream. maybe corrupted data.\n");
167 #ifdef __MMFILE_TEST_MODE__
168 debug_msg ("number of stream: %d\n", pFormatCtx->nb_streams);
171 formatContext->videoTotalTrackNum = 0;
172 formatContext->audioTotalTrackNum = 0;
174 for(i = 0; i < pFormatCtx->nb_streams; i++) {
175 #ifdef __MMFILE_FFMPEG_V085__
176 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
177 #ifdef __MMFILE_TEST_MODE__
178 debug_msg ("FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
180 if (ConvertVideoCodecEnum(pFormatCtx->streams[i]->codec->codec_id) != MM_VIDEO_CODEC_NONE)
181 formatContext->videoTotalTrackNum += 1;
183 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
184 #ifdef __MMFILE_TEST_MODE__
185 debug_msg ("FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
187 formatContext->audioTotalTrackNum += 1;
190 if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_VIDEO) {
191 #ifdef __MMFILE_TEST_MODE__
192 debug_msg ("FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
194 formatContext->videoTotalTrackNum += 1;
196 if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_AUDIO) {
197 #ifdef __MMFILE_TEST_MODE__
198 debug_msg ("FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
200 formatContext->audioTotalTrackNum += 1;
205 #ifdef __MMFILE_TEST_MODE__
206 debug_msg ("format: %s (%s)\n", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
207 #ifdef __MMFILE_FFMPEG_V085__
208 av_dump_format (pFormatCtx, 0, formatContext->filesrc->file.path, 0);
210 dump_format (pFormatCtx, 0, formatContext->filesrc->file.path, 0);
214 return MMFILE_FORMAT_SUCCESS;
216 exception: /* fail to get content information */
218 mmfile_format_close_ffmpg (formatContext);
219 formatContext->privateFormatData = NULL;
221 return MMFILE_FORMAT_FAIL;
226 int mmfile_format_read_stream_ffmpg (MMFileFormatContext * formatContext)
228 AVFormatContext *pFormatCtx = NULL;
229 AVCodecContext *pAudioCodecCtx = NULL;
230 AVCodecContext *pVideoCodecCtx = NULL;
232 MMFileFormatStream *videoStream = NULL;
233 MMFileFormatStream *audioStream = NULL;
236 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
237 debug_error ("invalid param\n");
238 return MMFILE_FORMAT_FAIL;
241 pFormatCtx = formatContext->privateFormatData;
244 *@important if data is corrupted, occur segment fault by av_find_stream_info().
245 * - fixed 2009-06-25.
247 #ifdef __MMFILE_FFMPEG_V100__
248 ret = avformat_find_stream_info (pFormatCtx, NULL);
250 ret = av_find_stream_info (pFormatCtx);
253 debug_warning ("failed to find stream info. errcode = %d\n", ret);
257 #ifdef __MMFILE_TEST_MODE__
258 debug_msg ("FFMPEG: dur %lld, start %lld\n", pFormatCtx->duration, pFormatCtx->start_time);
262 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
264 if(pFormatCtx->start_time < 0) {
265 debug_warning ("Wrong Start time = %lld\n", pFormatCtx->start_time);
266 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
269 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
272 formatContext->videoStreamId = -1;
273 formatContext->audioStreamId = -1;
274 formatContext->nbStreams = 0;
277 for ( i = 0; i < pFormatCtx->nb_streams; i++ ) {
278 #ifdef __MMFILE_FFMPEG_V085__
279 if ( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
281 if ( pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_VIDEO) {
283 if (formatContext->videoStreamId == -1) {
284 videoStream = mmfile_malloc (sizeof(MMFileFormatStream));
285 if (NULL == videoStream) {
286 debug_error ("mmfile_malloc error\n");
290 videoStream->streamType = MMFILE_VIDEO_STREAM;
291 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
292 formatContext->nbStreams += 1;
293 formatContext->videoStreamId = i;
295 pVideoCodecCtx = pFormatCtx->streams[i]->codec;
296 if (pVideoCodecCtx) {
297 videoStream->codecId = ConvertVideoCodecEnum (pVideoCodecCtx->codec_id);
298 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
299 debug_error("Proper codec is not found in [%d] stream", i);
300 formatContext->videoStreamId = -1;
301 mmfile_free(videoStream);
302 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
309 * 1. try to get average fps of video stream.
310 * 2. if (1) failed, try to get fps of media container.
312 videoStream->framePerSec = _get_video_fps (pFormatCtx->streams[i]->nb_frames,
313 pFormatCtx->streams[i]->duration,
314 pFormatCtx->streams[i]->time_base,
316 if (videoStream->framePerSec == 0) {
317 #ifndef __MMFILE_LIBAV_VERSION__
318 videoStream->framePerSec = av_q2d (pFormatCtx->streams[i]->r_frame_rate);
320 videoStream->framePerSec = av_q2d (pFormatCtx->streams[i]->avg_frame_rate);
324 videoStream->width = pVideoCodecCtx->width;
325 videoStream->height = pVideoCodecCtx->height;
326 videoStream->bitRate = pVideoCodecCtx->bit_rate;
330 #ifdef __MMFILE_FFMPEG_V085__
331 else if ( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) {
333 else if ( pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_AUDIO ) {
335 if (formatContext->audioStreamId == -1) {
336 audioStream = mmfile_malloc (sizeof(MMFileFormatStream));
337 if (NULL == audioStream) {
338 debug_error ("mmfile_malloc error\n");
342 audioStream->streamType = MMFILE_AUDIO_STREAM;
343 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
344 formatContext->nbStreams += 1;
345 formatContext->audioStreamId = i;
347 pAudioCodecCtx = pFormatCtx->streams[i]->codec;
348 if (pAudioCodecCtx) {
349 audioStream->codecId = ConvertAudioCodecEnum (pAudioCodecCtx->codec_id);
350 audioStream->bitRate = pAudioCodecCtx->bit_rate;
351 audioStream->nbChannel = pAudioCodecCtx->channels;
352 audioStream->samplePerSec = pAudioCodecCtx->sample_rate;
358 if ( formatContext->nbStreams == 0 ) {
359 debug_error("error: there is no audio and video track\n");
363 #ifdef __MMFILE_TEST_MODE__
364 mmfile_format_print_contents (formatContext);
367 return MMFILE_FORMAT_SUCCESS;
371 mmfile_free (videoStream);
372 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
376 mmfile_free (audioStream);
377 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
381 #ifdef __MMFILE_FFMPEG_V100__
382 avformat_close_input (&pFormatCtx);
384 av_close_input_file (pFormatCtx);
386 formatContext->privateFormatData = NULL;
389 formatContext->audioTotalTrackNum = 0;
390 formatContext->videoTotalTrackNum = 0;
391 formatContext->nbStreams = 0;
393 return MMFILE_FORMAT_FAIL;
396 #define DATA_LENGTH 4
397 #define POS_OF_MIME_LEN DATA_LENGTH
398 #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 |src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]);}
401 int mmfile_format_read_tag_ffmpg (MMFileFormatContext *formatContext)
403 AVFormatContext *pFormatCtx = NULL;
405 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
406 debug_error ("invalid param\n");
407 return MMFILE_FORMAT_FAIL;
410 pFormatCtx = formatContext->privateFormatData;
412 if (formatContext->formatType == MM_FILE_FORMAT_3GP ||formatContext->formatType == MM_FILE_FORMAT_MP4) {
413 MMFileUtilGetMetaDataFromMP4 (formatContext);
416 #ifdef __MMFILE_FFMPEG_V085__
417 /*metadata extracted by ffmpeg*/
420 if(pFormatCtx != NULL) {
421 for(idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
422 AVDictionary *metainfo = NULL;
425 if(idx < pFormatCtx->nb_streams) { //Check metadata of normal stream like audio, video, video cover art(cover art saved in new stream). refer to mov_read_covr() in ffmpeg.
426 st = pFormatCtx->streams[idx];
428 metainfo = st->metadata;
429 } else { //Check metadata of Content
430 if(pFormatCtx->metadata != NULL) {
431 metainfo = pFormatCtx->metadata;
437 /*refer to mov_read_covr() in ffmpeg.*/
439 AVPacket pkt = st->attached_pic;
440 int codec_id = st->codec->codec_id;
442 if((pkt.data != NULL) && (pkt.size > 0)) {
444 if (formatContext->artworkMime) mmfile_free (formatContext->artworkMime);
446 if(codec_id == AV_CODEC_ID_MJPEG)
447 formatContext->artworkMime = mmfile_strdup("image/jpeg");
448 else if(codec_id == AV_CODEC_ID_PNG)
449 formatContext->artworkMime = mmfile_strdup("image/png");
450 else if(codec_id == AV_CODEC_ID_BMP)
451 formatContext->artworkMime = mmfile_strdup("image/bmp");
453 debug_error ("Unknown cover type: 0x%x\n", codec_id);
456 if (formatContext->artwork) mmfile_free (formatContext->artwork);
458 formatContext->artworkSize = pkt.size;
459 formatContext->artwork = mmfile_malloc (pkt.size);
460 memcpy (formatContext->artwork, pkt.data, pkt.size);
464 if(metainfo != NULL) {
465 AVDictionaryEntry *tag = NULL;
466 while((tag=av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
467 if(tag->key != NULL) {
468 if(!strcasecmp(tag->key, "title")) {
469 if (formatContext->title) free (formatContext->title);
470 formatContext->title = mmfile_strdup (tag->value);
471 } else if(!strcasecmp(tag->key, "artist")) {
472 if (formatContext->artist) free (formatContext->artist);
473 formatContext->artist = mmfile_strdup (tag->value);
474 } else if(!strcasecmp(tag->key, "composer")) {
475 if (formatContext->composer) free (formatContext->composer);
476 formatContext->composer = mmfile_strdup (tag->value);
477 } else if(!strcasecmp(tag->key, "album")) {
478 if (formatContext->album) free (formatContext->album);
479 formatContext->album = mmfile_strdup (tag->value);
480 } else if(!strcasecmp(tag->key, "copyright")) {
481 if (formatContext->copyright) free (formatContext->copyright);
482 formatContext->copyright = mmfile_strdup (tag->value);
483 } else if(!strcasecmp(tag->key, "comment")) {
484 if (formatContext->comment) free (formatContext->comment);
485 formatContext->comment = mmfile_strdup (tag->value);
486 } else if(!strcasecmp(tag->key, "description")) {
487 if (formatContext->description) free (formatContext->description);
488 formatContext->description = mmfile_strdup (tag->value);
489 } else if(!strcasecmp(tag->key, "genre")) {
490 if (formatContext->genre) free (formatContext->genre);
491 formatContext->genre = mmfile_strdup (tag->value);
492 } else if(!strcasecmp(tag->key, "date")) {
493 if (formatContext->year) free (formatContext->year);
494 formatContext->year = mmfile_strdup (tag->value);
495 } else if((!strcasecmp(tag->key, "track")) || (!strcasecmp(tag->key, "tracknumber"))) {
496 if (formatContext->tagTrackNum) free (formatContext->tagTrackNum);
497 formatContext->tagTrackNum = mmfile_strdup (tag->value);
498 } else if(!strcasecmp(tag->key, "lyrics")) {
499 if (formatContext->unsyncLyrics) free (formatContext->unsyncLyrics);
500 formatContext->unsyncLyrics= mmfile_strdup (tag->value);
501 } else if(!strcasecmp(tag->key, "rotate")) { //can be "90", "180", "270"
502 if (formatContext->rotate) free (formatContext->rotate);
503 formatContext->rotate= mmfile_strdup (tag->value);
504 } else if(!strcasecmp(tag->key, "metadata_block_picture")) {
506 guchar *meta_data = NULL;
508 meta_data = g_base64_decode(tag->value, &len);
509 if (meta_data != NULL) {
510 /* in METADATA_BLOCK_PICTURE,
511 the length of mime type and the length of description are flexible,
512 so, we have to get the length of their for getting correct postion of picture data. */
514 int description_len = 0;
517 unsigned char current_data[DATA_LENGTH] = {0};
519 /* get length of mime_type */
520 memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH);
521 CONVERT_TO_INT(mime_len, current_data);
523 /* get length of description */
524 current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */
525 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
526 CONVERT_TO_INT(description_len, current_data);
528 /* get length of picture data */
529 current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */
530 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
531 CONVERT_TO_INT(data_len, current_data);
533 /* set the size of art work */
534 formatContext->artworkSize = data_len;
537 current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */
538 if (formatContext->artworkMime) mmfile_free (formatContext->artworkMime);
539 formatContext->artworkMime = strndup((const char*)meta_data + current_pos, mime_len);
541 /* set art work data */
542 current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */
543 if (formatContext->artwork) mmfile_free (formatContext->artwork);
544 formatContext->artwork = mmfile_malloc (data_len);
545 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
550 debug_log("Not support metadata. [%s:%s]", tag->key, tag->value);
555 #ifdef __MMFILE_TEST_MODE__
556 mmfile_format_print_tags (formatContext);
561 if (pFormatCtx->title[0]) {
562 if (formatContext->title)
563 free (formatContext->title);
564 formatContext->title = mmfile_strdup (pFormatCtx->title);
566 if (pFormatCtx->author[0]){
567 if (formatContext->author)
568 free (formatContext->author);
569 formatContext->author = mmfile_strdup (pFormatCtx->author);
571 if (pFormatCtx->copyright[0]) {
572 if (formatContext->copyright)
573 free (formatContext->copyright);
574 formatContext->copyright = mmfile_strdup (pFormatCtx->copyright);
576 if (pFormatCtx->comment[0]) {
577 if (formatContext->comment)
578 free (formatContext->comment);
579 formatContext->comment = mmfile_strdup (pFormatCtx->comment);
581 if (pFormatCtx->album[0]) {
582 if (formatContext->album)
583 free (formatContext->album);
584 formatContext->album = mmfile_strdup (pFormatCtx->album);
586 if (pFormatCtx->genre[0]) {
587 if (formatContext->genre)
588 free (formatContext->genre);
589 formatContext->genre = mmfile_strdup (pFormatCtx->genre);
592 if (pFormatCtx->year) {
593 char year[10] = {0,};
594 snprintf (year, 10, "%d", pFormatCtx->year);
596 if (formatContext->year)
597 free (formatContext->year);
598 formatContext->year = mmfile_strdup (year);
601 if (pFormatCtx->track) {
602 char tracknum[10] = {0,};
603 snprintf (tracknum, 10, "%d", pFormatCtx->track);
605 if (formatContext->tagTrackNum)
606 free (formatContext->tagTrackNum);
607 formatContext->tagTrackNum = mmfile_strdup (tracknum);
611 return MMFILE_FORMAT_SUCCESS;
616 int mmfile_format_read_frame_ffmpg (MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
618 AVFormatContext *pFormatCtx = NULL;
619 AVCodecContext *pVideoCodecCtx = NULL;
620 AVCodec *pVideoCodec = NULL;
621 AVFrame *pFrame = NULL;
622 AVFrame *pFrameRGB = NULL;
629 if (NULL == formatContext ||
631 NULL == formatContext->privateFormatData ||
632 formatContext->videoTotalTrackNum <= 0) {
634 debug_error ("invalid param\n");
635 return MMFILE_FORMAT_FAIL;
638 pFormatCtx = formatContext->privateFormatData;
640 if (formatContext->videoStreamId != -1) {
641 pVideoCodecCtx = pFormatCtx->streams[formatContext->videoStreamId]->codec;
642 if (NULL == pVideoCodecCtx) {
643 debug_error ("invalid param\n");
644 return MMFILE_FORMAT_FAIL;
647 pVideoCodec = avcodec_find_decoder (pVideoCodecCtx->codec_id);
648 if ( NULL == pVideoCodec ) {
649 debug_error ("error: avcodec_find_decoder failed\n");
650 return MMFILE_FORMAT_FAIL;
653 #ifdef __MMFILE_TEST_MODE__
654 debug_msg ("flag: 0x%08X\n", pVideoCodec->capabilities);
655 // debug_msg (" DRAW_HORIZ_BAND : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0);
656 // debug_msg (" DR1 : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DR1 ? 1 : 0);
657 // debug_msg (" PARSE_ONLY : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_PARSE_ONLY ? 1 : 0);
658 // debug_msg (" TRUNCATED : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_TRUNCATED ? 1 : 0);
659 // debug_msg (" HWACCEL : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_HWACCEL ? 1 : 0);
660 // debug_msg (" DELAY : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DELAY ? 1 : 0);
661 // debug_msg (" SMALL_LAST_FRAME: %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0);
662 // debug_msg (" HWACCEL_VDPAU : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU ? 1 : 0);
665 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
666 pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
669 /*set workaround bug flag*/
670 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
671 #ifdef __MMFILE_FFMPEG_V100__
672 ret = avcodec_open2 (pVideoCodecCtx, pVideoCodec, NULL);
674 ret = avcodec_open (pVideoCodecCtx, pVideoCodec);
677 debug_error ("error: avcodec_open fail.\n");
678 return MMFILE_FORMAT_FAIL;
681 pFrameRGB = avcodec_alloc_frame ();
684 debug_error ("error: pFrame or pFrameRGB is NULL\n");
685 ret = MMFILE_FORMAT_FAIL;
689 /* search & decode */
690 // seek_ts = formatContext->duration > _SHORT_MEDIA_LIMIT ? seek_ts : 0; /*if short media, seek first key frame*/
691 ret = _get_first_good_video_frame (pFormatCtx, pVideoCodecCtx, formatContext->videoStreamId, &pFrame);
692 if ( ret != MMFILE_FORMAT_SUCCESS ) {
693 debug_error ("error: get key frame\n");
694 ret = MMFILE_FORMAT_FAIL;
698 #ifdef __MMFILE_TEST_MODE__
699 debug_msg ("Video default resolution = [%dx%d]\n", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
700 debug_msg ("Video coded resolution = [%dx%d]\n", pVideoCodecCtx->width, pVideoCodecCtx->height);
703 /*sometimes, ffmpeg's width/height is wrong*/
704 #if 0 /*coded_width/height sometimes wrong. so use width/height*/
705 width = pVideoCodecCtx->coded_width == 0 ? pVideoCodecCtx->width : pVideoCodecCtx->coded_width;
706 height = pVideoCodecCtx->coded_height == 0 ? pVideoCodecCtx->height : pVideoCodecCtx->coded_height;
708 if((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
709 width = pVideoCodecCtx->coded_width;
710 height = pVideoCodecCtx->coded_height;
712 width = pVideoCodecCtx->width;
713 height = pVideoCodecCtx->height;
716 numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
718 debug_error ("error: avpicture_get_size. [%d x %d]\n", width, height);
719 ret = MMFILE_FORMAT_FAIL;
723 frame->frameData = mmfile_malloc (numBytes);
724 if (NULL == frame->frameData) {
725 debug_error ("error: avpicture_get_size. [%d]\n", numBytes);
726 ret = MMFILE_FORMAT_FAIL;
730 ret = avpicture_fill ((AVPicture *)pFrameRGB, frame->frameData, PIX_FMT_RGB24, width, height);
732 debug_error ("error: avpicture_fill fail. errcode = 0x%08X\n", ret);
733 ret = MMFILE_FORMAT_FAIL;
737 #ifdef __MMFILE_FFMPEG_V085__
738 struct SwsContext *img_convert_ctx = NULL;
740 img_convert_ctx = sws_getContext (width, height, pVideoCodecCtx->pix_fmt,
741 width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
743 if (NULL == img_convert_ctx) {
744 debug_error ("failed to get img convet ctx\n");
745 ret = MMFILE_FORMAT_FAIL;
749 ret = sws_scale (img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
750 0, height, pFrameRGB->data, pFrameRGB->linesize);
752 debug_error ("failed to convet image\n");
753 ret = MMFILE_FORMAT_FAIL;
754 sws_freeContext(img_convert_ctx);
755 img_convert_ctx = NULL;
759 sws_freeContext(img_convert_ctx);
760 img_convert_ctx = NULL;
762 ret = img_convert ((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pVideoCodecCtx->pix_fmt, width, height);
764 debug_error ("failed to convet image\n");
765 ret = MMFILE_FORMAT_FAIL;
769 frame->frameSize = numBytes;
770 frame->frameWidth = width;
771 frame->frameHeight = height;
772 frame->configLenth = 0;
773 frame->bCompressed = 0; /* false */
775 if (pFrame) av_free (pFrame);
776 if (pFrameRGB) av_free (pFrameRGB);
778 avcodec_close(pVideoCodecCtx);
780 return MMFILE_FORMAT_SUCCESS;
785 if (pVideoCodecCtx) avcodec_close (pVideoCodecCtx);
786 if (frame->frameData) { mmfile_free (frame->frameData); frame->frameData = NULL; }
787 if (pFrame) av_free (pFrame);
788 if (pFrameRGB) av_free (pFrameRGB);
794 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
797 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
800 #ifdef __MMFILE_FFMPEG_V100__
801 avformat_close_input(&pFormatCtx);
803 av_close_input_file (pFormatCtx);
805 formatContext->privateFormatData = NULL;
809 return MMFILE_FORMAT_SUCCESS;
813 * return average of difference
815 static unsigned int _diff_memory (const void *s1, const void *s2, unsigned int n)
817 char *s = (char *)s1;
818 char *d = (char *)s2;
823 for (i = 0, ret = 0; i < n; i++) {
826 ret += (tmp < 0 ? -tmp : tmp);
833 int64_t gettime(void)
836 gettimeofday(&tv,NULL);
837 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
841 #define IS_GOOD_OLD_METHOD
842 #ifdef IS_GOOD_OLD_METHOD
844 * compare with center line.
846 static int _is_good_pgm (unsigned char *buf, int wrap, int xsize, int ysize)
848 #define _MM_CHUNK_NUM 8 /*FIXME*/
849 #define _MM_CHUNK_LIMIT (_MM_CHUNK_NUM / 2)
850 #define _MM_CHUNK_DIFF_LIMIT (_MM_CHUNK_LIMIT * 2 + 1) /*FIXME*/
855 unsigned char *cnt; /*center line of image*/
857 unsigned int sum_diff;
861 step = ysize / _MM_CHUNK_NUM;
862 cnt_offset = (ysize / 2);
863 cnt = buf + cnt_offset * wrap;
865 #ifdef __MMFILE_TEST_MODE__
866 debug_msg ("checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
869 /*if too small, always ok return.*/
870 if (ysize < _MM_CHUNK_NUM)
873 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
874 if (i != cnt_offset) {
877 is_different = _diff_memory (cnt, buf + i * wrap, xsize);
878 point += (is_different == 0 ? 0 : 1);
879 sum_diff += is_different;
881 #ifdef __MMFILE_TEST_MODE__
882 debug_msg ("check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
885 if (point >= _MM_CHUNK_LIMIT) {
886 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
887 #ifdef __MMFILE_TEST_MODE__
888 debug_msg ("Good :-)\n");
892 #ifdef __MMFILE_TEST_MODE__
893 debug_msg ("Bad :-(\n");
903 #else // IS_GOOD_OLD_METHOD
904 /* ToDo : for enhancement */
905 #endif // IS_GOOD_OLD_METHOD
910 _get_video_fps (int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
914 #ifdef __MMFILE_TEST_MODE__
915 debug_msg ("frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den)
918 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
921 round = (is_roundup != 0 ? 0.50f : 0.00f);
923 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
928 #ifdef MMFILE_FORMAT_DEBUG_DUMP
929 static void _save_pgm (unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
934 f = fopen(filename,"w");
936 fprintf (f,"P5\n%d %d\n%d\n",xsize,ysize,255);
937 for (i = 0; i < ysize; i++)
938 fwrite (buf + i * wrap, 1, xsize, f);
944 #ifdef __MMFILE_TEST_MODE__
945 static void _dump_av_packet (AVPacket *pkt)
947 debug_msg ("--------- AV Packet -----------\n");
948 debug_msg (" pts: %lld\n", pkt->pts);
949 debug_msg (" dts: %lld\n", pkt->dts);
950 debug_msg (" data: %p\n", pkt->data);
951 debug_msg (" size: %d\n", pkt->size);
952 debug_msg (" stream_index: %d\n", pkt->stream_index);
953 #ifdef __MMFILE_FFMPEG_V085__
954 debug_msg (" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
956 debug_msg (" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & PKT_FLAG_KEY) ? "Keyframe" : "_");
958 debug_msg (" duration: %d\n", pkt->duration);
959 debug_msg (" destruct: %p\n", pkt->destruct);
960 debug_msg (" priv: %p\n", pkt->priv);
961 debug_msg (" pos: %lld\n", pkt->pos);
962 debug_msg (" convergence_duration: %lld\n", pkt->convergence_duration);
963 debug_msg ("-------------------------------\n");
967 static int _get_first_good_video_frame (AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame)
969 // AVStream *st = NULL;
972 AVFrame *frame = NULL;
973 AVFrame *tmp_frame = NULL;
974 AVFrame *first_frame = NULL;
976 // long long timestamp;
977 int stream_id = videoStream;
980 int i,v, len, got_picture;
983 #ifdef MMFILE_FORMAT_DEBUG_DUMP
984 char pgm_name[256] = {0,};
987 #define _RETRY_SEARCH_LIMIT 150
988 #define _KEY_SEARCH_LIMIT (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
989 #define _FRAME_SEARCH_LIMIT 1000
991 first_frame = avcodec_alloc_frame ();
992 tmp_frame = avcodec_alloc_frame ();
994 if (!first_frame || !tmp_frame) {
995 debug_error ("failed to alloc frame.\n");
996 if (first_frame) av_free (first_frame);
997 if (tmp_frame) av_free (tmp_frame);
998 return MMFILE_FORMAT_FAIL;
1001 #ifdef __MMFILE_TEST_MODE__
1002 debug_msg ("frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1005 #ifdef __MMFILE_FFMPEG_V085__
1006 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1008 pCodecCtx->hurry_up = 1;
1011 for(i = 0, v = 0, key_detected = 0, frame = first_frame; i < _KEY_SEARCH_LIMIT && v < _FRAME_SEARCH_LIMIT;) {
1012 av_init_packet (&pkt);
1015 ret = av_read_frame (pFormatCtx, &pkt);
1017 debug_error ("read failed. (maybe EOF or broken)\n");
1020 if (pkt.stream_index == stream_id) {
1022 #ifdef __MMFILE_FFMPEG_V085__
1023 if ((pkt.flags & AV_PKT_FLAG_KEY ) || (key_detected == 1))
1025 if ((pkt.flags & PKT_FLAG_KEY ) || (key_detected == 1))
1028 #ifdef __MMFILE_TEST_MODE__
1029 debug_msg ("video frame: %d, %d, %d\n", retry, i, v);
1030 _dump_av_packet (&pkt);
1035 #ifdef __MMFILE_FFMPEG_V085__
1036 len = avcodec_decode_video2 (pCodecCtx, frame, &got_picture, &pkt);
1038 len = avcodec_decode_video (pCodecCtx, frame, &got_picture, pkt.data, pkt.size);
1041 debug_warning ("Error while decoding frame %dth\n", i);
1042 } else if (got_picture) {
1043 if (frame->key_frame) {
1044 #ifdef __MMFILE_TEST_MODE__
1045 debug_msg ("key frame!\n");
1047 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1048 sprintf (pgm_name, "./key_%d_%d_%d.pgm", retry, i, v);
1049 _save_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1054 #ifdef __MMFILE_TEST_MODE__
1058 ret = _is_good_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1059 #ifdef __MMFILE_TEST_MODE__
1060 ti = gettime() - ti;
1061 debug_msg ("Elapsed time = %lld\n", ti);
1064 #ifdef __MMFILE_TEST_MODE__
1065 debug_msg ("is good frame.\n");
1069 /*reset video frame count & retry searching*/
1070 debug_warning ("not good fame. retry scanning.\n");
1076 /*set buffer frame*/
1080 if (retry > _RETRY_SEARCH_LIMIT) break;
1083 #ifdef __MMFILE_TEST_MODE__
1084 debug_msg ("skip (not key frame).\n");
1086 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1087 sprintf (pgm_name, "./not_key_%d_%d_%d.pgm", retry, i, v);
1088 _save_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1092 #ifdef __MMFILE_TEST_MODE__
1093 debug_msg ("decode not completed.\n");
1100 av_free_packet (&pkt);
1103 /*free pkt after loop breaking*/
1104 if (pkt.data) av_free_packet (&pkt);
1106 #ifdef __MMFILE_TEST_MODE__
1107 debug_msg ("found: %d, retry: %d\n", found, retry);
1110 /*set decode frame to output*/
1112 ret = MMFILE_FORMAT_SUCCESS;
1113 if (retry == 0 || found == retry) {
1114 *pFrame = first_frame;
1115 if (tmp_frame) av_free (tmp_frame);
1117 *pFrame = tmp_frame;
1118 if (first_frame) av_free (first_frame);
1121 ret = MMFILE_FORMAT_FAIL;
1122 if (first_frame) av_free (first_frame);
1123 if (tmp_frame) av_free (tmp_frame);
1126 #ifdef __MMFILE_TEST_MODE__
1127 debug_msg ("out frame: %p\n", *pFrame);
1130 #ifdef __MMFILE_FFMPEG_V085__
1131 pCodecCtx->skip_frame = AVDISCARD_NONE;
1133 pCodecCtx->hurry_up = 0;
1139 static int ConvertVideoCodecEnum (int AVVideoCodecID)
1141 int ret_codecid = 0;
1143 switch (AVVideoCodecID)
1145 case AV_CODEC_ID_NONE:
1146 ret_codecid = MM_VIDEO_CODEC_NONE;
1148 case AV_CODEC_ID_MPEG1VIDEO:
1149 ret_codecid = MM_VIDEO_CODEC_MPEG1;
1151 case AV_CODEC_ID_MPEG2VIDEO: ///< preferred ID for MPEG-1/2 video decoding
1152 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1154 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1155 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1157 case AV_CODEC_ID_H261:
1158 ret_codecid = MM_VIDEO_CODEC_H261;
1160 case AV_CODEC_ID_H263:
1161 ret_codecid = MM_VIDEO_CODEC_H263;
1163 case AV_CODEC_ID_MPEG4:
1164 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1166 case AV_CODEC_ID_MSMPEG4V1:
1167 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1169 case AV_CODEC_ID_MSMPEG4V2:
1170 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1172 case AV_CODEC_ID_MSMPEG4V3:
1173 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1175 case AV_CODEC_ID_WMV1:
1176 ret_codecid = MM_VIDEO_CODEC_WMV;
1178 case AV_CODEC_ID_WMV2:
1179 ret_codecid = MM_VIDEO_CODEC_WMV;
1181 case AV_CODEC_ID_H263P:
1182 ret_codecid = MM_VIDEO_CODEC_H263;
1184 case AV_CODEC_ID_H263I:
1185 ret_codecid = MM_VIDEO_CODEC_H263;
1187 case AV_CODEC_ID_FLV1:
1188 ret_codecid = MM_VIDEO_CODEC_FLV;
1190 case AV_CODEC_ID_H264:
1191 ret_codecid = MM_VIDEO_CODEC_H264;
1193 case AV_CODEC_ID_INDEO2:
1194 case AV_CODEC_ID_INDEO3:
1195 case AV_CODEC_ID_INDEO4:
1196 case AV_CODEC_ID_INDEO5:
1197 ret_codecid = MM_VIDEO_CODEC_INDEO;
1199 case AV_CODEC_ID_THEORA:
1200 ret_codecid = MM_VIDEO_CODEC_THEORA;
1202 case AV_CODEC_ID_CINEPAK:
1203 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1205 #if (!defined __MMFILE_FFMPEG_V085__ && !defined __MMFILE_LIBAV_VERSION__)
1206 case AV_CODEC_ID_XVID:
1207 ret_codecid = MM_VIDEO_CODEC_XVID;
1210 case AV_CODEC_ID_VC1:
1211 ret_codecid = MM_VIDEO_CODEC_VC1;
1213 case AV_CODEC_ID_WMV3:
1214 ret_codecid = MM_VIDEO_CODEC_WMV;
1216 case AV_CODEC_ID_AVS:
1217 ret_codecid = MM_VIDEO_CODEC_AVS;
1219 case AV_CODEC_ID_RL2:
1220 ret_codecid = MM_VIDEO_CODEC_REAL;
1223 ret_codecid = MM_VIDEO_CODEC_NONE;
1231 static int ConvertAudioCodecEnum (int AVAudioCodecID)
1233 int ret_codecid = 0;
1235 switch (AVAudioCodecID)
1237 case AV_CODEC_ID_AMR_NB:
1238 case AV_CODEC_ID_AMR_WB:
1239 ret_codecid = MM_AUDIO_CODEC_AMR;
1241 /* RealAudio codecs*/
1242 case AV_CODEC_ID_RA_144:
1243 case AV_CODEC_ID_RA_288:
1244 ret_codecid = MM_AUDIO_CODEC_REAL;
1246 case AV_CODEC_ID_MP2:
1247 ret_codecid = MM_AUDIO_CODEC_MP2;
1249 case AV_CODEC_ID_MP3:
1250 case AV_CODEC_ID_MP3ADU:
1251 case AV_CODEC_ID_MP3ON4:
1252 ret_codecid = MM_AUDIO_CODEC_MP3;
1254 case AV_CODEC_ID_AAC:
1255 ret_codecid = MM_AUDIO_CODEC_AAC;
1257 case AV_CODEC_ID_AC3:
1258 ret_codecid = MM_AUDIO_CODEC_AC3;
1260 case AV_CODEC_ID_VORBIS:
1261 ret_codecid = MM_AUDIO_CODEC_VORBIS;
1263 case AV_CODEC_ID_WMAV1:
1264 case AV_CODEC_ID_WMAV2:
1265 case AV_CODEC_ID_WMAVOICE:
1266 case AV_CODEC_ID_WMAPRO:
1267 case AV_CODEC_ID_WMALOSSLESS:
1268 ret_codecid = MM_AUDIO_CODEC_WMA;
1270 case AV_CODEC_ID_FLAC:
1271 ret_codecid = MM_AUDIO_CODEC_FLAC;
1273 case AV_CODEC_ID_ALAC:
1274 ret_codecid = MM_AUDIO_CODEC_ALAC;
1276 case AV_CODEC_ID_WAVPACK:
1277 ret_codecid = MM_AUDIO_CODEC_WAVE;
1279 case AV_CODEC_ID_ATRAC3:
1280 case AV_CODEC_ID_ATRAC3P:
1281 case AV_CODEC_ID_EAC3:
1282 ret_codecid = MM_AUDIO_CODEC_AC3;
1285 ret_codecid = MM_AUDIO_CODEC_NONE;
1294 static int getMimeType(int formatId, char *mimeType)
1296 int ret = 0; /*default: success*/
1299 case MM_FILE_FORMAT_3GP:
1300 case MM_FILE_FORMAT_MP4:
1301 sprintf(mimeType,"video/3gpp");
1303 case MM_FILE_FORMAT_ASF:
1304 case MM_FILE_FORMAT_WMA:
1305 case MM_FILE_FORMAT_WMV:
1306 sprintf(mimeType,"video/x-ms-asf");
1308 case MM_FILE_FORMAT_AVI:
1309 sprintf(mimeType,"video/avi");
1311 case MM_FILE_FORMAT_OGG:
1312 sprintf(mimeType,"video/ogg");
1314 case MM_FILE_FORMAT_REAL:
1315 sprintf(mimeType,"video/vnd.rn-realvideo");
1317 case MM_FILE_FORMAT_AMR:
1318 sprintf(mimeType,"audio/AMR");
1320 case MM_FILE_FORMAT_AAC:
1321 sprintf(mimeType,"audio/aac");
1323 case MM_FILE_FORMAT_MP3:
1324 sprintf(mimeType,"audio/mp3");
1326 case MM_FILE_FORMAT_AIFF:
1327 case MM_FILE_FORMAT_WAV:
1328 sprintf(mimeType,"audio/wave");
1330 case MM_FILE_FORMAT_MID:
1331 sprintf(mimeType,"audio/midi");
1333 case MM_FILE_FORMAT_MMF:
1334 sprintf(mimeType,"audio/mmf");
1336 case MM_FILE_FORMAT_DIVX:
1337 sprintf(mimeType,"video/divx");
1339 case MM_FILE_FORMAT_IMELODY:
1340 sprintf(mimeType,"audio/iMelody");
1342 case MM_FILE_FORMAT_JPG:
1343 sprintf(mimeType,"image/jpeg");
1345 case MM_FILE_FORMAT_AU:
1346 sprintf(mimeType,"audio/basic");
1348 case MM_FILE_FORMAT_VOB:
1349 sprintf(mimeType,"video/mpeg");
1351 case MM_FILE_FORMAT_FLV:
1352 sprintf(mimeType,"video/x-flv");
1354 case MM_FILE_FORMAT_QT:
1355 sprintf(mimeType,"video/quicktime");
1357 case MM_FILE_FORMAT_MATROSKA:
1358 sprintf(mimeType,"video/x-matroska");
1360 case MM_FILE_FORMAT_FLAC:
1361 sprintf(mimeType,"audio/x-flac");
1367 debug_msg ("id: %d, mimetype: %s\n", formatId, mimeType);