Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * THP Demuxer
  3.  * Copyright (c) 2007 Marco Gerards
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/intreadwrite.h"
  23. #include "libavutil/intfloat.h"
  24. #include "avformat.h"
  25. #include "internal.h"
  26.  
  27. typedef struct ThpDemuxContext {
  28.     int              version;
  29.     unsigned         first_frame;
  30.     unsigned         first_framesz;
  31.     unsigned         last_frame;
  32.     int              compoff;
  33.     unsigned         framecnt;
  34.     AVRational       fps;
  35.     unsigned         frame;
  36.     int64_t          next_frame;
  37.     unsigned         next_framesz;
  38.     int              video_stream_index;
  39.     int              audio_stream_index;
  40.     int              compcount;
  41.     unsigned char    components[16];
  42.     AVStream*        vst;
  43.     int              has_audio;
  44.     unsigned         audiosize;
  45. } ThpDemuxContext;
  46.  
  47.  
  48. static int thp_probe(AVProbeData *p)
  49. {
  50.     /* check file header */
  51.     if (AV_RL32(p->buf) == MKTAG('T', 'H', 'P', '\0'))
  52.         return AVPROBE_SCORE_MAX;
  53.     else
  54.         return 0;
  55. }
  56.  
  57. static int thp_read_header(AVFormatContext *s)
  58. {
  59.     ThpDemuxContext *thp = s->priv_data;
  60.     AVStream *st;
  61.     AVIOContext *pb = s->pb;
  62.     int64_t fsize= avio_size(pb);
  63.     int i;
  64.  
  65.     /* Read the file header.  */
  66.                            avio_rb32(pb); /* Skip Magic.  */
  67.     thp->version         = avio_rb32(pb);
  68.  
  69.                            avio_rb32(pb); /* Max buf size.  */
  70.                            avio_rb32(pb); /* Max samples.  */
  71.  
  72.     thp->fps             = av_d2q(av_int2float(avio_rb32(pb)), INT_MAX);
  73.     thp->framecnt        = avio_rb32(pb);
  74.     thp->first_framesz   = avio_rb32(pb);
  75.     pb->maxsize          = avio_rb32(pb);
  76.     if(fsize>0 && (!pb->maxsize || fsize < pb->maxsize))
  77.         pb->maxsize= fsize;
  78.  
  79.     thp->compoff         = avio_rb32(pb);
  80.                            avio_rb32(pb); /* offsetDataOffset.  */
  81.     thp->first_frame     = avio_rb32(pb);
  82.     thp->last_frame      = avio_rb32(pb);
  83.  
  84.     thp->next_framesz    = thp->first_framesz;
  85.     thp->next_frame      = thp->first_frame;
  86.  
  87.     /* Read the component structure.  */
  88.     avio_seek (pb, thp->compoff, SEEK_SET);
  89.     thp->compcount       = avio_rb32(pb);
  90.  
  91.     /* Read the list of component types.  */
  92.     avio_read(pb, thp->components, 16);
  93.  
  94.     for (i = 0; i < thp->compcount; i++) {
  95.         if (thp->components[i] == 0) {
  96.             if (thp->vst != 0)
  97.                 break;
  98.  
  99.             /* Video component.  */
  100.             st = avformat_new_stream(s, NULL);
  101.             if (!st)
  102.                 return AVERROR(ENOMEM);
  103.  
  104.             /* The denominator and numerator are switched because 1/fps
  105.                is required.  */
  106.             avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
  107.             st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  108.             st->codec->codec_id = AV_CODEC_ID_THP;
  109.             st->codec->codec_tag = 0;  /* no fourcc */
  110.             st->codec->width = avio_rb32(pb);
  111.             st->codec->height = avio_rb32(pb);
  112.             st->codec->sample_rate = av_q2d(thp->fps);
  113.             st->nb_frames =
  114.             st->duration = thp->framecnt;
  115.             thp->vst = st;
  116.             thp->video_stream_index = st->index;
  117.  
  118.             if (thp->version == 0x11000)
  119.                 avio_rb32(pb); /* Unknown.  */
  120.         } else if (thp->components[i] == 1) {
  121.             if (thp->has_audio != 0)
  122.                 break;
  123.  
  124.             /* Audio component.  */
  125.             st = avformat_new_stream(s, NULL);
  126.             if (!st)
  127.                 return AVERROR(ENOMEM);
  128.  
  129.             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  130.             st->codec->codec_id = AV_CODEC_ID_ADPCM_THP;
  131.             st->codec->codec_tag = 0;  /* no fourcc */
  132.             st->codec->channels    = avio_rb32(pb); /* numChannels.  */
  133.             st->codec->sample_rate = avio_rb32(pb); /* Frequency.  */
  134.  
  135.             avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
  136.  
  137.             thp->audio_stream_index = st->index;
  138.             thp->has_audio = 1;
  139.         }
  140.     }
  141.  
  142.     return 0;
  143. }
  144.  
  145. static int thp_read_packet(AVFormatContext *s,
  146.                             AVPacket *pkt)
  147. {
  148.     ThpDemuxContext *thp = s->priv_data;
  149.     AVIOContext *pb = s->pb;
  150.     unsigned int size;
  151.     int ret;
  152.  
  153.     if (thp->audiosize == 0) {
  154.         /* Terminate when last frame is reached.  */
  155.         if (thp->frame >= thp->framecnt)
  156.             return AVERROR_EOF;
  157.  
  158.         avio_seek(pb, thp->next_frame, SEEK_SET);
  159.  
  160.         /* Locate the next frame and read out its size.  */
  161.         thp->next_frame += FFMAX(thp->next_framesz, 1);
  162.         thp->next_framesz = avio_rb32(pb);
  163.  
  164.                         avio_rb32(pb); /* Previous total size.  */
  165.         size          = avio_rb32(pb); /* Total size of this frame.  */
  166.  
  167.         /* Store the audiosize so the next time this function is called,
  168.            the audio can be read.  */
  169.         if (thp->has_audio)
  170.             thp->audiosize = avio_rb32(pb); /* Audio size.  */
  171.         else
  172.             thp->frame++;
  173.  
  174.         ret = av_get_packet(pb, pkt, size);
  175.         if (ret != size) {
  176.             av_free_packet(pkt);
  177.             return AVERROR(EIO);
  178.         }
  179.  
  180.         pkt->stream_index = thp->video_stream_index;
  181.     } else {
  182.         ret = av_get_packet(pb, pkt, thp->audiosize);
  183.         if (ret != thp->audiosize) {
  184.             av_free_packet(pkt);
  185.             return AVERROR(EIO);
  186.         }
  187.  
  188.         pkt->stream_index = thp->audio_stream_index;
  189.         if (thp->audiosize >= 8)
  190.             pkt->duration = AV_RB32(&pkt->data[4]);
  191.  
  192.         thp->audiosize = 0;
  193.         thp->frame++;
  194.     }
  195.  
  196.     return 0;
  197. }
  198.  
  199. AVInputFormat ff_thp_demuxer = {
  200.     .name           = "thp",
  201.     .long_name      = NULL_IF_CONFIG_SMALL("THP"),
  202.     .priv_data_size = sizeof(ThpDemuxContext),
  203.     .read_probe     = thp_probe,
  204.     .read_header    = thp_read_header,
  205.     .read_packet    = thp_read_packet
  206. };
  207.