00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/bswap.h"
00028 #include "avformat.h"
00029
00030 #define MTV_ASUBCHUNK_DATA_SIZE 500
00031 #define MTV_HEADER_SIZE 512
00032 #define MTV_AUDIO_PADDING_SIZE 12
00033 #define AUDIO_SAMPLING_RATE 44100
00034 #define VIDEO_SID 0
00035 #define AUDIO_SID 1
00036
00037 typedef struct MTVDemuxContext {
00038
00039 unsigned int file_size;
00040 unsigned int segments;
00041 unsigned int audio_identifier;
00042 unsigned int audio_br;
00043 unsigned int img_colorfmt;
00044 unsigned int img_bpp;
00045 unsigned int img_width;
00046 unsigned int img_height;
00047 unsigned int img_segment_size;
00048 unsigned int video_fps;
00049 unsigned int full_segment_size;
00050
00051 } MTVDemuxContext;
00052
00053 static int mtv_probe(AVProbeData *p)
00054 {
00055
00056 if(*(p->buf) != 'A' || *(p->buf+1) != 'M' || *(p->buf+2) != 'V')
00057 return 0;
00058
00059 return AVPROBE_SCORE_MAX;
00060 }
00061
00062 static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00063 {
00064 MTVDemuxContext *mtv = s->priv_data;
00065 ByteIOContext *pb = s->pb;
00066 AVStream *st;
00067 unsigned int audio_subsegments;
00068
00069 url_fskip(pb, 3);
00070 mtv->file_size = get_le32(pb);
00071 mtv->segments = get_le32(pb);
00072 url_fskip(pb, 32);
00073 mtv->audio_identifier = get_le24(pb);
00074 mtv->audio_br = get_le16(pb);
00075 mtv->img_colorfmt = get_le24(pb);
00076 mtv->img_bpp = get_byte(pb);
00077 mtv->img_width = get_le16(pb);
00078 mtv->img_height = get_le16(pb);
00079 mtv->img_segment_size = get_le16(pb);
00080 url_fskip(pb, 4);
00081 audio_subsegments = get_le16(pb);
00082 mtv->full_segment_size =
00083 audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) +
00084 mtv->img_segment_size;
00085 mtv->video_fps = (mtv->audio_br / 4) / audio_subsegments;
00086
00087
00088
00089
00090
00091
00092
00093 st = av_new_stream(s, VIDEO_SID);
00094 if(!st)
00095 return AVERROR(ENOMEM);
00096
00097 av_set_pts_info(st, 64, 1, mtv->video_fps);
00098 st->codec->codec_type = CODEC_TYPE_VIDEO;
00099 st->codec->codec_id = CODEC_ID_RAWVIDEO;
00100 st->codec->codec_tag = MKTAG('R', 'G', 'B', mtv->img_bpp);
00101 st->codec->width = mtv->img_width;
00102 st->codec->height = mtv->img_height;
00103 st->codec->bits_per_coded_sample = mtv->img_bpp;
00104 st->codec->sample_rate = mtv->video_fps;
00105
00106
00107
00108 st = av_new_stream(s, AUDIO_SID);
00109 if(!st)
00110 return AVERROR(ENOMEM);
00111
00112 av_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE);
00113 st->codec->codec_type = CODEC_TYPE_AUDIO;
00114 st->codec->codec_id = CODEC_ID_MP3;
00115 st->codec->bit_rate = mtv->audio_br;
00116 st->need_parsing = AVSTREAM_PARSE_FULL;
00117
00118
00119
00120 if(url_fseek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE)
00121 return AVERROR(EIO);
00122
00123 return 0;
00124
00125 }
00126
00127 static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
00128 {
00129 MTVDemuxContext *mtv = s->priv_data;
00130 ByteIOContext *pb = s->pb;
00131 int ret;
00132 #ifndef WORDS_BIGENDIAN
00133 int i;
00134 #endif
00135
00136 ret = 0;
00137
00138 if((url_ftell(pb) - s->data_offset + mtv->img_segment_size) % mtv->full_segment_size)
00139 {
00140 url_fskip(pb, MTV_AUDIO_PADDING_SIZE);
00141
00142 ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);
00143 if(ret != MTV_ASUBCHUNK_DATA_SIZE)
00144 return AVERROR(EIO);
00145
00146 pkt->pos -= MTV_AUDIO_PADDING_SIZE;
00147 pkt->stream_index = AUDIO_SID;
00148
00149 }else
00150 {
00151 ret = av_get_packet(pb, pkt, mtv->img_segment_size);
00152 if(ret != mtv->img_segment_size)
00153 return AVERROR(EIO);
00154
00155 #ifndef WORDS_BIGENDIAN
00156
00157
00158
00159
00160
00161
00162
00163 for(i=0;i<mtv->img_segment_size/2;i++)
00164 *((uint16_t *)pkt->data+i) = bswap_16(*((uint16_t *)pkt->data+i));
00165 #endif
00166 pkt->stream_index = VIDEO_SID;
00167 }
00168
00169 return ret;
00170 }
00171
00172 AVInputFormat mtv_demuxer = {
00173 "MTV",
00174 NULL_IF_CONFIG_SMALL("MTV format"),
00175 sizeof(MTVDemuxContext),
00176 mtv_probe,
00177 mtv_read_header,
00178 mtv_read_packet,
00179 };