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 AVFormatParameters *ap)
00059 {
00060 ThpDemuxContext *thp = s->priv_data;
00061 AVStream *st;
00062 AVIOContext *pb = s->pb;
00063 int64_t fsize= avio_size(pb);
00064 int i;
00065
00066
00067 avio_rb32(pb);
00068 thp->version = avio_rb32(pb);
00069
00070 avio_rb32(pb);
00071 avio_rb32(pb);
00072
00073 thp->fps = av_d2q(av_int2float(avio_rb32(pb)), INT_MAX);
00074 thp->framecnt = avio_rb32(pb);
00075 thp->first_framesz = avio_rb32(pb);
00076 pb->maxsize = avio_rb32(pb);
00077 if(fsize>0 && (!pb->maxsize || fsize < pb->maxsize))
00078 pb->maxsize= fsize;
00079
00080 thp->compoff = avio_rb32(pb);
00081 avio_rb32(pb);
00082 thp->first_frame = avio_rb32(pb);
00083 thp->last_frame = avio_rb32(pb);
00084
00085 thp->next_framesz = thp->first_framesz;
00086 thp->next_frame = thp->first_frame;
00087
00088
00089 avio_seek (pb, thp->compoff, SEEK_SET);
00090 thp->compcount = avio_rb32(pb);
00091
00092
00093 avio_read(pb, thp->components, 16);
00094
00095 for (i = 0; i < thp->compcount; i++) {
00096 if (thp->components[i] == 0) {
00097 if (thp->vst != 0)
00098 break;
00099
00100
00101 st = avformat_new_stream(s, NULL);
00102 if (!st)
00103 return AVERROR(ENOMEM);
00104
00105
00106
00107 avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
00108 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00109 st->codec->codec_id = CODEC_ID_THP;
00110 st->codec->codec_tag = 0;
00111 st->codec->width = avio_rb32(pb);
00112 st->codec->height = avio_rb32(pb);
00113 st->codec->sample_rate = av_q2d(thp->fps);
00114 thp->vst = st;
00115 thp->video_stream_index = st->index;
00116
00117 if (thp->version == 0x11000)
00118 avio_rb32(pb);
00119 } else if (thp->components[i] == 1) {
00120 if (thp->has_audio != 0)
00121 break;
00122
00123
00124 st = avformat_new_stream(s, NULL);
00125 if (!st)
00126 return AVERROR(ENOMEM);
00127
00128 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00129 st->codec->codec_id = CODEC_ID_ADPCM_THP;
00130 st->codec->codec_tag = 0;
00131 st->codec->channels = avio_rb32(pb);
00132 st->codec->sample_rate = avio_rb32(pb);
00133
00134 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00135
00136 thp->audio_stream_index = st->index;
00137 thp->has_audio = 1;
00138 }
00139 }
00140
00141 return 0;
00142 }
00143
00144 static int thp_read_packet(AVFormatContext *s,
00145 AVPacket *pkt)
00146 {
00147 ThpDemuxContext *thp = s->priv_data;
00148 AVIOContext *pb = s->pb;
00149 unsigned int size;
00150 int ret;
00151
00152 if (thp->audiosize == 0) {
00153
00154 if (thp->frame >= thp->framecnt)
00155 return AVERROR(EIO);
00156
00157 avio_seek(pb, thp->next_frame, SEEK_SET);
00158
00159
00160 thp->next_frame += thp->next_framesz;
00161 thp->next_framesz = avio_rb32(pb);
00162
00163 avio_rb32(pb);
00164 size = avio_rb32(pb);
00165
00166
00167
00168 if (thp->has_audio)
00169 thp->audiosize = avio_rb32(pb);
00170 else
00171 thp->frame++;
00172
00173 ret = av_get_packet(pb, pkt, size);
00174 if (ret != size) {
00175 av_free_packet(pkt);
00176 return AVERROR(EIO);
00177 }
00178
00179 pkt->stream_index = thp->video_stream_index;
00180 } else {
00181 ret = av_get_packet(pb, pkt, thp->audiosize);
00182 if (ret != thp->audiosize) {
00183 av_free_packet(pkt);
00184 return AVERROR(EIO);
00185 }
00186
00187 pkt->stream_index = thp->audio_stream_index;
00188 thp->audiosize = 0;
00189 thp->frame++;
00190 }
00191
00192 return 0;
00193 }
00194
00195 AVInputFormat ff_thp_demuxer = {
00196 .name = "thp",
00197 .long_name = NULL_IF_CONFIG_SMALL("THP"),
00198 .priv_data_size = sizeof(ThpDemuxContext),
00199 .read_probe = thp_probe,
00200 .read_header = thp_read_header,
00201 .read_packet = thp_read_packet
00202 };