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