• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/mm.c

Go to the documentation of this file.
00001 /*
00002  * American Laser Games MM Format Demuxer
00003  * Copyright (c) 2006 Peter Ross
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00034 #include "libavutil/intreadwrite.h"
00035 #include "avformat.h"
00036 
00037 #define MM_PREAMBLE_SIZE    6
00038 
00039 #define MM_TYPE_HEADER      0x0
00040 #define MM_TYPE_INTER       0x5
00041 #define MM_TYPE_INTRA       0x8
00042 #define MM_TYPE_INTRA_HH    0xc
00043 #define MM_TYPE_INTER_HH    0xd
00044 #define MM_TYPE_INTRA_HHV   0xe
00045 #define MM_TYPE_INTER_HHV   0xf
00046 #define MM_TYPE_AUDIO       0x15
00047 #define MM_TYPE_PALETTE     0x31
00048 
00049 #define MM_HEADER_LEN_V     0x16    /* video only */
00050 #define MM_HEADER_LEN_AV    0x18    /* video + audio */
00051 
00052 #define MM_PALETTE_COUNT    128
00053 #define MM_PALETTE_SIZE     (MM_PALETTE_COUNT*3)
00054 
00055 typedef struct {
00056   unsigned int audio_pts, video_pts;
00057 } MmDemuxContext;
00058 
00059 static int probe(AVProbeData *p)
00060 {
00061     int len, type, fps, w, h;
00062     if (p->buf_size < MM_HEADER_LEN_AV + MM_PREAMBLE_SIZE)
00063         return 0;
00064     /* the first chunk is always the header */
00065     if (AV_RL16(&p->buf[0]) != MM_TYPE_HEADER)
00066         return 0;
00067     len = AV_RL32(&p->buf[2]);
00068     if (len != MM_HEADER_LEN_V && len != MM_HEADER_LEN_AV)
00069         return 0;
00070     fps = AV_RL16(&p->buf[8]);
00071     w = AV_RL16(&p->buf[12]);
00072     h = AV_RL16(&p->buf[14]);
00073     if (!fps || fps > 60 || !w || w > 2048 || !h || h > 2048)
00074         return 0;
00075     type = AV_RL16(&p->buf[len]);
00076     if (!type || type > 0x31)
00077         return 0;
00078 
00079     /* only return half certainty since this check is a bit sketchy */
00080     return AVPROBE_SCORE_MAX / 2;
00081 }
00082 
00083 static int read_header(AVFormatContext *s,
00084                            AVFormatParameters *ap)
00085 {
00086     MmDemuxContext *mm = s->priv_data;
00087     ByteIOContext *pb = s->pb;
00088     AVStream *st;
00089 
00090     unsigned int type, length;
00091     unsigned int frame_rate, width, height;
00092 
00093     type = get_le16(pb);
00094     length = get_le32(pb);
00095 
00096     if (type != MM_TYPE_HEADER)
00097         return AVERROR_INVALIDDATA;
00098 
00099     /* read header */
00100     get_le16(pb);   /* total number of chunks */
00101     frame_rate = get_le16(pb);
00102     get_le16(pb);   /* ibm-pc video bios mode */
00103     width = get_le16(pb);
00104     height = get_le16(pb);
00105     url_fseek(pb, length - 10, SEEK_CUR);  /* unknown data */
00106 
00107     /* video stream */
00108     st = av_new_stream(s, 0);
00109     if (!st)
00110         return AVERROR(ENOMEM);
00111     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00112     st->codec->codec_id = CODEC_ID_MMVIDEO;
00113     st->codec->codec_tag = 0;  /* no fourcc */
00114     st->codec->width = width;
00115     st->codec->height = height;
00116     av_set_pts_info(st, 64, 1, frame_rate);
00117 
00118     /* audio stream */
00119     if (length == MM_HEADER_LEN_AV) {
00120         st = av_new_stream(s, 0);
00121         if (!st)
00122             return AVERROR(ENOMEM);
00123         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00124         st->codec->codec_tag = 0; /* no fourcc */
00125         st->codec->codec_id = CODEC_ID_PCM_U8;
00126         st->codec->channels = 1;
00127         st->codec->sample_rate = 8000;
00128         av_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
00129     }
00130 
00131     mm->audio_pts = 0;
00132     mm->video_pts = 0;
00133     return 0;
00134 }
00135 
00136 static int read_packet(AVFormatContext *s,
00137                            AVPacket *pkt)
00138 {
00139     MmDemuxContext *mm = s->priv_data;
00140     ByteIOContext *pb = s->pb;
00141     unsigned char preamble[MM_PREAMBLE_SIZE];
00142     unsigned int type, length;
00143 
00144     while(1) {
00145 
00146         if (get_buffer(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
00147             return AVERROR(EIO);
00148         }
00149 
00150         type = AV_RL16(&preamble[0]);
00151         length = AV_RL16(&preamble[2]);
00152 
00153         switch(type) {
00154         case MM_TYPE_PALETTE :
00155         case MM_TYPE_INTER :
00156         case MM_TYPE_INTRA :
00157         case MM_TYPE_INTRA_HH :
00158         case MM_TYPE_INTER_HH :
00159         case MM_TYPE_INTRA_HHV :
00160         case MM_TYPE_INTER_HHV :
00161             /* output preamble + data */
00162             if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
00163                 return AVERROR(ENOMEM);
00164             memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
00165             if (get_buffer(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
00166                 return AVERROR(EIO);
00167             pkt->size = length + MM_PREAMBLE_SIZE;
00168             pkt->stream_index = 0;
00169             pkt->pts = mm->video_pts;
00170             if (type!=MM_TYPE_PALETTE)
00171                 mm->video_pts++;
00172             return 0;
00173 
00174         case MM_TYPE_AUDIO :
00175             if (av_get_packet(s->pb, pkt, length)<0)
00176                 return AVERROR(ENOMEM);
00177             pkt->size = length;
00178             pkt->stream_index = 1;
00179             pkt->pts = mm->audio_pts++;
00180             return 0;
00181 
00182         default :
00183             av_log(s, AV_LOG_INFO, "unknown chunk type 0x%x\n", type);
00184             url_fseek(pb, length, SEEK_CUR);
00185         }
00186     }
00187 
00188     return 0;
00189 }
00190 
00191 AVInputFormat mm_demuxer = {
00192     "mm",
00193     NULL_IF_CONFIG_SMALL("American Laser Games MM format"),
00194     sizeof(MmDemuxContext),
00195     probe,
00196     read_header,
00197     read_packet,
00198 };

Generated on Fri Sep 16 2011 17:17:49 for FFmpeg by  doxygen 1.7.1