• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/thp.c

Go to the documentation of this file.
00001 /*
00002  * THP Demuxer
00003  * Copyright (c) 2007 Marco Gerards
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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     int              audiosize;
00045 } ThpDemuxContext;
00046 
00047 
00048 static int thp_probe(AVProbeData *p)
00049 {
00050     /* check file header */
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     int i;
00064 
00065     /* Read the file header.  */
00066                            avio_rb32(pb); /* Skip Magic.  */
00067     thp->version         = avio_rb32(pb);
00068 
00069                            avio_rb32(pb); /* Max buf size.  */
00070                            avio_rb32(pb); /* Max samples.  */
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                            avio_rb32(pb); /* Data size.  */
00076 
00077     thp->compoff         = avio_rb32(pb);
00078                            avio_rb32(pb); /* offsetDataOffset.  */
00079     thp->first_frame     = avio_rb32(pb);
00080     thp->last_frame      = avio_rb32(pb);
00081 
00082     thp->next_framesz    = thp->first_framesz;
00083     thp->next_frame      = thp->first_frame;
00084 
00085     /* Read the component structure.  */
00086     avio_seek (pb, thp->compoff, SEEK_SET);
00087     thp->compcount       = avio_rb32(pb);
00088 
00089     /* Read the list of component types.  */
00090     avio_read(pb, thp->components, 16);
00091 
00092     for (i = 0; i < thp->compcount; i++) {
00093         if (thp->components[i] == 0) {
00094             if (thp->vst != 0)
00095                 break;
00096 
00097             /* Video component.  */
00098             st = avformat_new_stream(s, NULL);
00099             if (!st)
00100                 return AVERROR(ENOMEM);
00101 
00102             /* The denominator and numerator are switched because 1/fps
00103                is required.  */
00104             avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
00105             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00106             st->codec->codec_id = CODEC_ID_THP;
00107             st->codec->codec_tag = 0;  /* no fourcc */
00108             st->codec->width = avio_rb32(pb);
00109             st->codec->height = avio_rb32(pb);
00110             st->codec->sample_rate = av_q2d(thp->fps);
00111             thp->vst = st;
00112             thp->video_stream_index = st->index;
00113 
00114             if (thp->version == 0x11000)
00115                 avio_rb32(pb); /* Unknown.  */
00116         } else if (thp->components[i] == 1) {
00117             if (thp->has_audio != 0)
00118                 break;
00119 
00120             /* Audio component.  */
00121             st = avformat_new_stream(s, NULL);
00122             if (!st)
00123                 return AVERROR(ENOMEM);
00124 
00125             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00126             st->codec->codec_id = CODEC_ID_ADPCM_THP;
00127             st->codec->codec_tag = 0;  /* no fourcc */
00128             st->codec->channels    = avio_rb32(pb); /* numChannels.  */
00129             st->codec->sample_rate = avio_rb32(pb); /* Frequency.  */
00130 
00131             avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00132 
00133             thp->audio_stream_index = st->index;
00134             thp->has_audio = 1;
00135         }
00136     }
00137 
00138     return 0;
00139 }
00140 
00141 static int thp_read_packet(AVFormatContext *s,
00142                             AVPacket *pkt)
00143 {
00144     ThpDemuxContext *thp = s->priv_data;
00145     AVIOContext *pb = s->pb;
00146     int size;
00147     int ret;
00148 
00149     if (thp->audiosize == 0) {
00150         /* Terminate when last frame is reached.  */
00151         if (thp->frame >= thp->framecnt)
00152             return AVERROR(EIO);
00153 
00154         avio_seek(pb, thp->next_frame, SEEK_SET);
00155 
00156         /* Locate the next frame and read out its size.  */
00157         thp->next_frame += thp->next_framesz;
00158         thp->next_framesz = avio_rb32(pb);
00159 
00160                         avio_rb32(pb); /* Previous total size.  */
00161         size          = avio_rb32(pb); /* Total size of this frame.  */
00162 
00163         /* Store the audiosize so the next time this function is called,
00164            the audio can be read.  */
00165         if (thp->has_audio)
00166             thp->audiosize = avio_rb32(pb); /* Audio size.  */
00167         else
00168             thp->frame++;
00169 
00170         ret = av_get_packet(pb, pkt, size);
00171         if (ret != size) {
00172             av_free_packet(pkt);
00173             return AVERROR(EIO);
00174         }
00175 
00176         pkt->stream_index = thp->video_stream_index;
00177     } else {
00178         ret = av_get_packet(pb, pkt, thp->audiosize);
00179         if (ret != thp->audiosize) {
00180             av_free_packet(pkt);
00181             return AVERROR(EIO);
00182         }
00183 
00184         pkt->stream_index = thp->audio_stream_index;
00185         thp->audiosize = 0;
00186         thp->frame++;
00187     }
00188 
00189     return 0;
00190 }
00191 
00192 AVInputFormat ff_thp_demuxer = {
00193     .name           = "thp",
00194     .long_name      = NULL_IF_CONFIG_SMALL("THP"),
00195     .priv_data_size = sizeof(ThpDemuxContext),
00196     .read_probe     = thp_probe,
00197     .read_header    = thp_read_header,
00198     .read_packet    = thp_read_packet
00199 };
Generated on Sat Mar 17 2012 12:57:55 for Libav by doxygen 1.7.1