00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "avformat.h"
00024
00025 typedef struct ThpDemuxContext {
00026 int version;
00027 int first_frame;
00028 int first_framesz;
00029 int last_frame;
00030 int compoff;
00031 int framecnt;
00032 AVRational fps;
00033 int frame;
00034 int next_frame;
00035 int next_framesz;
00036 int video_stream_index;
00037 int audio_stream_index;
00038 int compcount;
00039 unsigned char components[16];
00040 AVStream* vst;
00041 int has_audio;
00042 int audiosize;
00043 } ThpDemuxContext;
00044
00045
00046 static int thp_probe(AVProbeData *p)
00047 {
00048
00049 if (AV_RL32(p->buf) == MKTAG('T', 'H', 'P', '\0'))
00050 return AVPROBE_SCORE_MAX;
00051 else
00052 return 0;
00053 }
00054
00055 static int thp_read_header(AVFormatContext *s,
00056 AVFormatParameters *ap)
00057 {
00058 ThpDemuxContext *thp = s->priv_data;
00059 AVStream *st;
00060 AVIOContext *pb = s->pb;
00061 int i;
00062
00063
00064 avio_rb32(pb);
00065 thp->version = avio_rb32(pb);
00066
00067 avio_rb32(pb);
00068 avio_rb32(pb);
00069
00070 thp->fps = av_d2q(av_int2flt(avio_rb32(pb)), INT_MAX);
00071 thp->framecnt = avio_rb32(pb);
00072 thp->first_framesz = avio_rb32(pb);
00073 avio_rb32(pb);
00074
00075 thp->compoff = avio_rb32(pb);
00076 avio_rb32(pb);
00077 thp->first_frame = avio_rb32(pb);
00078 thp->last_frame = avio_rb32(pb);
00079
00080 thp->next_framesz = thp->first_framesz;
00081 thp->next_frame = thp->first_frame;
00082
00083
00084 avio_seek (pb, thp->compoff, SEEK_SET);
00085 thp->compcount = avio_rb32(pb);
00086
00087
00088 avio_read(pb, thp->components, 16);
00089
00090 for (i = 0; i < thp->compcount; i++) {
00091 if (thp->components[i] == 0) {
00092 if (thp->vst != 0)
00093 break;
00094
00095
00096 st = av_new_stream(s, 0);
00097 if (!st)
00098 return AVERROR(ENOMEM);
00099
00100
00101
00102 av_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
00103 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00104 st->codec->codec_id = CODEC_ID_THP;
00105 st->codec->codec_tag = 0;
00106 st->codec->width = avio_rb32(pb);
00107 st->codec->height = avio_rb32(pb);
00108 st->codec->sample_rate = av_q2d(thp->fps);
00109 thp->vst = st;
00110 thp->video_stream_index = st->index;
00111
00112 if (thp->version == 0x11000)
00113 avio_rb32(pb);
00114 } else if (thp->components[i] == 1) {
00115 if (thp->has_audio != 0)
00116 break;
00117
00118
00119 st = av_new_stream(s, 0);
00120 if (!st)
00121 return AVERROR(ENOMEM);
00122
00123 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00124 st->codec->codec_id = CODEC_ID_ADPCM_THP;
00125 st->codec->codec_tag = 0;
00126 st->codec->channels = avio_rb32(pb);
00127 st->codec->sample_rate = avio_rb32(pb);
00128
00129 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00130
00131 thp->audio_stream_index = st->index;
00132 thp->has_audio = 1;
00133 }
00134 }
00135
00136 return 0;
00137 }
00138
00139 static int thp_read_packet(AVFormatContext *s,
00140 AVPacket *pkt)
00141 {
00142 ThpDemuxContext *thp = s->priv_data;
00143 AVIOContext *pb = s->pb;
00144 int size;
00145 int ret;
00146
00147 if (thp->audiosize == 0) {
00148
00149 if (thp->frame >= thp->framecnt)
00150 return AVERROR(EIO);
00151
00152 avio_seek(pb, thp->next_frame, SEEK_SET);
00153
00154
00155 thp->next_frame += thp->next_framesz;
00156 thp->next_framesz = avio_rb32(pb);
00157
00158 avio_rb32(pb);
00159 size = avio_rb32(pb);
00160
00161
00162
00163 if (thp->has_audio)
00164 thp->audiosize = avio_rb32(pb);
00165 else
00166 thp->frame++;
00167
00168 ret = av_get_packet(pb, pkt, size);
00169 if (ret != size) {
00170 av_free_packet(pkt);
00171 return AVERROR(EIO);
00172 }
00173
00174 pkt->stream_index = thp->video_stream_index;
00175 } else {
00176 ret = av_get_packet(pb, pkt, thp->audiosize);
00177 if (ret != thp->audiosize) {
00178 av_free_packet(pkt);
00179 return AVERROR(EIO);
00180 }
00181
00182 pkt->stream_index = thp->audio_stream_index;
00183 thp->audiosize = 0;
00184 thp->frame++;
00185 }
00186
00187 return 0;
00188 }
00189
00190 AVInputFormat ff_thp_demuxer = {
00191 "thp",
00192 NULL_IF_CONFIG_SMALL("THP"),
00193 sizeof(ThpDemuxContext),
00194 thp_probe,
00195 thp_read_header,
00196 thp_read_packet
00197 };