Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Westwood Studios VQA Format Demuxer
  3.  * Copyright (c) 2003 The ffmpeg Project
  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. /**
  23.  * @file
  24.  * Westwood Studios VQA file demuxer
  25.  * by Mike Melanson (melanson@pcisys.net)
  26.  * for more information on the Westwood file formats, visit:
  27.  *   http://www.pcisys.net/~melanson/codecs/
  28.  *   http://www.geocities.com/SiliconValley/8682/aud3.txt
  29.  */
  30.  
  31. #include "libavutil/intreadwrite.h"
  32. #include "avformat.h"
  33. #include "internal.h"
  34.  
  35. #define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
  36. #define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A')
  37. #define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D')
  38. #define FINF_TAG MKBETAG('F', 'I', 'N', 'F')
  39. #define SND0_TAG MKBETAG('S', 'N', 'D', '0')
  40. #define SND1_TAG MKBETAG('S', 'N', 'D', '1')
  41. #define SND2_TAG MKBETAG('S', 'N', 'D', '2')
  42. #define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R')
  43.  
  44. /* don't know what these tags are for, but acknowledge their existence */
  45. #define CINF_TAG MKBETAG('C', 'I', 'N', 'F')
  46. #define CINH_TAG MKBETAG('C', 'I', 'N', 'H')
  47. #define CIND_TAG MKBETAG('C', 'I', 'N', 'D')
  48. #define PINF_TAG MKBETAG('P', 'I', 'N', 'F')
  49. #define PINH_TAG MKBETAG('P', 'I', 'N', 'H')
  50. #define PIND_TAG MKBETAG('P', 'I', 'N', 'D')
  51. #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S')
  52.  
  53. #define VQA_HEADER_SIZE 0x2A
  54. #define VQA_PREAMBLE_SIZE 8
  55.  
  56. typedef struct WsVqaDemuxContext {
  57.     int version;
  58.     int bps;
  59.     int channels;
  60.     int sample_rate;
  61.     int audio_stream_index;
  62.     int video_stream_index;
  63. } WsVqaDemuxContext;
  64.  
  65. static int wsvqa_probe(AVProbeData *p)
  66. {
  67.     /* need 12 bytes to qualify */
  68.     if (p->buf_size < 12)
  69.         return 0;
  70.  
  71.     /* check for the VQA signatures */
  72.     if ((AV_RB32(&p->buf[0]) != FORM_TAG) ||
  73.         (AV_RB32(&p->buf[8]) != WVQA_TAG))
  74.         return 0;
  75.  
  76.     return AVPROBE_SCORE_MAX;
  77. }
  78.  
  79. static int wsvqa_read_header(AVFormatContext *s)
  80. {
  81.     WsVqaDemuxContext *wsvqa = s->priv_data;
  82.     AVIOContext *pb = s->pb;
  83.     AVStream *st;
  84.     uint8_t *header;
  85.     uint8_t scratch[VQA_PREAMBLE_SIZE];
  86.     uint32_t chunk_tag;
  87.     uint32_t chunk_size;
  88.     int fps;
  89.  
  90.     /* initialize the video decoder stream */
  91.     st = avformat_new_stream(s, NULL);
  92.     if (!st)
  93.         return AVERROR(ENOMEM);
  94.     st->start_time = 0;
  95.     wsvqa->video_stream_index = st->index;
  96.     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  97.     st->codec->codec_id = AV_CODEC_ID_WS_VQA;
  98.     st->codec->codec_tag = 0;  /* no fourcc */
  99.  
  100.     /* skip to the start of the VQA header */
  101.     avio_seek(pb, 20, SEEK_SET);
  102.  
  103.     /* the VQA header needs to go to the decoder */
  104.     if (ff_alloc_extradata(st->codec, VQA_HEADER_SIZE))
  105.         return AVERROR(ENOMEM);
  106.     header = (uint8_t *)st->codec->extradata;
  107.     if (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
  108.         VQA_HEADER_SIZE) {
  109.         return AVERROR(EIO);
  110.     }
  111.     st->codec->width = AV_RL16(&header[6]);
  112.     st->codec->height = AV_RL16(&header[8]);
  113.     fps = header[12];
  114.     st->nb_frames =
  115.     st->duration  = AV_RL16(&header[4]);
  116.     if (fps < 1 || fps > 30) {
  117.         av_log(s, AV_LOG_ERROR, "invalid fps: %d\n", fps);
  118.         return AVERROR_INVALIDDATA;
  119.     }
  120.     avpriv_set_pts_info(st, 64, 1, fps);
  121.  
  122.     wsvqa->version      = AV_RL16(&header[ 0]);
  123.     wsvqa->sample_rate  = AV_RL16(&header[24]);
  124.     wsvqa->channels     = header[26];
  125.     wsvqa->bps          = header[27];
  126.     wsvqa->audio_stream_index = -1;
  127.  
  128.     s->ctx_flags |= AVFMTCTX_NOHEADER;
  129.  
  130.     /* there are 0 or more chunks before the FINF chunk; iterate until
  131.      * FINF has been skipped and the file will be ready to be demuxed */
  132.     do {
  133.         if (avio_read(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE)
  134.             return AVERROR(EIO);
  135.         chunk_tag = AV_RB32(&scratch[0]);
  136.         chunk_size = AV_RB32(&scratch[4]);
  137.  
  138.         /* catch any unknown header tags, for curiousity */
  139.         switch (chunk_tag) {
  140.         case CINF_TAG:
  141.         case CINH_TAG:
  142.         case CIND_TAG:
  143.         case PINF_TAG:
  144.         case PINH_TAG:
  145.         case PIND_TAG:
  146.         case FINF_TAG:
  147.         case CMDS_TAG:
  148.             break;
  149.  
  150.         default:
  151.             av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
  152.                 scratch[0], scratch[1],
  153.                 scratch[2], scratch[3]);
  154.             break;
  155.         }
  156.  
  157.         avio_skip(pb, chunk_size);
  158.     } while (chunk_tag != FINF_TAG);
  159.  
  160.     return 0;
  161. }
  162.  
  163. static int wsvqa_read_packet(AVFormatContext *s,
  164.                              AVPacket *pkt)
  165. {
  166.     WsVqaDemuxContext *wsvqa = s->priv_data;
  167.     AVIOContext *pb = s->pb;
  168.     int ret = -1;
  169.     uint8_t preamble[VQA_PREAMBLE_SIZE];
  170.     uint32_t chunk_type;
  171.     uint32_t chunk_size;
  172.     int skip_byte;
  173.  
  174.     while (avio_read(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) {
  175.         chunk_type = AV_RB32(&preamble[0]);
  176.         chunk_size = AV_RB32(&preamble[4]);
  177.  
  178.         skip_byte = chunk_size & 0x01;
  179.  
  180.         if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) ||
  181.             (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
  182.  
  183.             ret= av_get_packet(pb, pkt, chunk_size);
  184.             if (ret<0)
  185.                 return AVERROR(EIO);
  186.  
  187.             switch (chunk_type) {
  188.             case SND0_TAG:
  189.             case SND1_TAG:
  190.             case SND2_TAG:
  191.                 if (wsvqa->audio_stream_index == -1) {
  192.                     AVStream *st = avformat_new_stream(s, NULL);
  193.                     if (!st)
  194.                         return AVERROR(ENOMEM);
  195.  
  196.                     wsvqa->audio_stream_index = st->index;
  197.                     if (!wsvqa->sample_rate)
  198.                         wsvqa->sample_rate = 22050;
  199.                     if (!wsvqa->channels)
  200.                         wsvqa->channels = 1;
  201.                     if (!wsvqa->bps)
  202.                         wsvqa->bps = 8;
  203.                     st->codec->sample_rate = wsvqa->sample_rate;
  204.                     st->codec->bits_per_coded_sample = wsvqa->bps;
  205.                     st->codec->channels = wsvqa->channels;
  206.                     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  207.  
  208.                     avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
  209.  
  210.                     switch (chunk_type) {
  211.                     case SND0_TAG:
  212.                         if (wsvqa->bps == 16)
  213.                             st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
  214.                         else
  215.                             st->codec->codec_id = AV_CODEC_ID_PCM_U8;
  216.                         break;
  217.                     case SND1_TAG:
  218.                         st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
  219.                         break;
  220.                     case SND2_TAG:
  221.                         st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
  222.                         if (ff_alloc_extradata(st->codec, 2))
  223.                             return AVERROR(ENOMEM);
  224.                         AV_WL16(st->codec->extradata, wsvqa->version);
  225.                         break;
  226.                     }
  227.                 }
  228.  
  229.                 pkt->stream_index = wsvqa->audio_stream_index;
  230.                 switch (chunk_type) {
  231.                 case SND1_TAG:
  232.                     /* unpacked size is stored in header */
  233.                     if(pkt->data)
  234.                         pkt->duration = AV_RL16(pkt->data) / wsvqa->channels;
  235.                     break;
  236.                 case SND2_TAG:
  237.                     /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
  238.                     pkt->duration = (chunk_size * 2) / wsvqa->channels;
  239.                     break;
  240.                 }
  241.                 break;
  242.             case VQFR_TAG:
  243.                 pkt->stream_index = wsvqa->video_stream_index;
  244.                 pkt->duration = 1;
  245.                 break;
  246.             }
  247.  
  248.             /* stay on 16-bit alignment */
  249.             if (skip_byte)
  250.                 avio_skip(pb, 1);
  251.  
  252.             return ret;
  253.         } else {
  254.             switch(chunk_type){
  255.             case CMDS_TAG:
  256.                 break;
  257.             default:
  258.                 av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type);
  259.             }
  260.             avio_skip(pb, chunk_size + skip_byte);
  261.         }
  262.     }
  263.  
  264.     return ret;
  265. }
  266.  
  267. AVInputFormat ff_wsvqa_demuxer = {
  268.     .name           = "wsvqa",
  269.     .long_name      = NULL_IF_CONFIG_SMALL("Westwood Studios VQA"),
  270.     .priv_data_size = sizeof(WsVqaDemuxContext),
  271.     .read_probe     = wsvqa_probe,
  272.     .read_header    = wsvqa_read_header,
  273.     .read_packet    = wsvqa_read_packet,
  274. };
  275.