• 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 mm_probe(AVProbeData *p)
00060 {
00061     /* the first chunk is always the header */
00062     if (AV_RL16(&p->buf[0]) != MM_TYPE_HEADER)
00063         return 0;
00064     if (AV_RL32(&p->buf[2]) != MM_HEADER_LEN_V && AV_RL32(&p->buf[2]) != MM_HEADER_LEN_AV)
00065         return 0;
00066 
00067     /* only return half certainty since this check is a bit sketchy */
00068     return AVPROBE_SCORE_MAX / 2;
00069 }
00070 
00071 static int mm_read_header(AVFormatContext *s,
00072                            AVFormatParameters *ap)
00073 {
00074     MmDemuxContext *mm = s->priv_data;
00075     ByteIOContext *pb = s->pb;
00076     AVStream *st;
00077 
00078     unsigned int type, length;
00079     unsigned int frame_rate, width, height;
00080 
00081     type = get_le16(pb);
00082     length = get_le32(pb);
00083 
00084     if (type != MM_TYPE_HEADER)
00085         return AVERROR_INVALIDDATA;
00086 
00087     /* read header */
00088     get_le16(pb);   /* total number of chunks */
00089     frame_rate = get_le16(pb);
00090     get_le16(pb);   /* ibm-pc video bios mode */
00091     width = get_le16(pb);
00092     height = get_le16(pb);
00093     url_fseek(pb, length - 10, SEEK_CUR);  /* unknown data */
00094 
00095     /* video stream */
00096     st = av_new_stream(s, 0);
00097     if (!st)
00098         return AVERROR(ENOMEM);
00099     st->codec->codec_type = CODEC_TYPE_VIDEO;
00100     st->codec->codec_id = CODEC_ID_MMVIDEO;
00101     st->codec->codec_tag = 0;  /* no fourcc */
00102     st->codec->width = width;
00103     st->codec->height = height;
00104     av_set_pts_info(st, 64, 1, frame_rate);
00105 
00106     /* audio stream */
00107     if (length == MM_HEADER_LEN_AV) {
00108         st = av_new_stream(s, 0);
00109         if (!st)
00110             return AVERROR(ENOMEM);
00111         st->codec->codec_type = CODEC_TYPE_AUDIO;
00112         st->codec->codec_tag = 0; /* no fourcc */
00113         st->codec->codec_id = CODEC_ID_PCM_U8;
00114         st->codec->channels = 1;
00115         st->codec->sample_rate = 8000;
00116         av_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
00117     }
00118 
00119     mm->audio_pts = 0;
00120     mm->video_pts = 0;
00121     return 0;
00122 }
00123 
00124 static int mm_read_packet(AVFormatContext *s,
00125                            AVPacket *pkt)
00126 {
00127     MmDemuxContext *mm = s->priv_data;
00128     ByteIOContext *pb = s->pb;
00129     unsigned char preamble[MM_PREAMBLE_SIZE];
00130     unsigned int type, length;
00131 
00132     while(1) {
00133 
00134         if (get_buffer(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
00135             return AVERROR(EIO);
00136         }
00137 
00138         type = AV_RL16(&preamble[0]);
00139         length = AV_RL16(&preamble[2]);
00140 
00141         switch(type) {
00142         case MM_TYPE_PALETTE :
00143         case MM_TYPE_INTER :
00144         case MM_TYPE_INTRA :
00145         case MM_TYPE_INTRA_HH :
00146         case MM_TYPE_INTER_HH :
00147         case MM_TYPE_INTRA_HHV :
00148         case MM_TYPE_INTER_HHV :
00149             /* output preamble + data */
00150             if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
00151                 return AVERROR(ENOMEM);
00152             memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
00153             if (get_buffer(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
00154                 return AVERROR(EIO);
00155             pkt->size = length + MM_PREAMBLE_SIZE;
00156             pkt->stream_index = 0;
00157             pkt->pts = mm->video_pts;
00158             if (type!=MM_TYPE_PALETTE)
00159                 mm->video_pts++;
00160             return 0;
00161 
00162         case MM_TYPE_AUDIO :
00163             if (av_get_packet(s->pb, pkt, length)<0)
00164                 return AVERROR(ENOMEM);
00165             pkt->size = length;
00166             pkt->stream_index = 1;
00167             pkt->pts = mm->audio_pts++;
00168             return 0;
00169 
00170         default :
00171             av_log(s, AV_LOG_INFO, "unknown chunk type 0x%x\n", type);
00172             url_fseek(pb, length, SEEK_CUR);
00173         }
00174     }
00175 
00176     return 0;
00177 }
00178 
00179 AVInputFormat mm_demuxer = {
00180     "mm",
00181     NULL_IF_CONFIG_SMALL("American Laser Games MM format"),
00182     sizeof(MmDemuxContext),
00183     mm_probe,
00184     mm_read_header,
00185     mm_read_packet,
00186 };

Generated on Sat Feb 16 2013 09:23:14 for ffmpeg by  doxygen 1.7.1