Subversion Repositories Kolibri OS

Rev

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_get_extradata(st->codec, pb, VQA_HEADER_SIZE) < 0)
  105.         return AVERROR(ENOMEM);
  106.     header = st->codec->extradata;
  107.     st->codec->width = AV_RL16(&header[6]);
  108.     st->codec->height = AV_RL16(&header[8]);
  109.     fps = header[12];
  110.     st->nb_frames =
  111.     st->duration  = AV_RL16(&header[4]);
  112.     if (fps < 1 || fps > 30) {
  113.         av_log(s, AV_LOG_ERROR, "invalid fps: %d\n", fps);
  114.         return AVERROR_INVALIDDATA;
  115.     }
  116.     avpriv_set_pts_info(st, 64, 1, fps);
  117.  
  118.     wsvqa->version      = AV_RL16(&header[ 0]);
  119.     wsvqa->sample_rate  = AV_RL16(&header[24]);
  120.     wsvqa->channels     = header[26];
  121.     wsvqa->bps          = header[27];
  122.     wsvqa->audio_stream_index = -1;
  123.  
  124.     s->ctx_flags |= AVFMTCTX_NOHEADER;
  125.  
  126.     /* there are 0 or more chunks before the FINF chunk; iterate until
  127.      * FINF has been skipped and the file will be ready to be demuxed */
  128.     do {
  129.         if (avio_read(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE)
  130.             return AVERROR(EIO);
  131.         chunk_tag = AV_RB32(&scratch[0]);
  132.         chunk_size = AV_RB32(&scratch[4]);
  133.  
  134.         /* catch any unknown header tags, for curiousity */
  135.         switch (chunk_tag) {
  136.         case CINF_TAG:
  137.         case CINH_TAG:
  138.         case CIND_TAG:
  139.         case PINF_TAG:
  140.         case PINH_TAG:
  141.         case PIND_TAG:
  142.         case FINF_TAG:
  143.         case CMDS_TAG:
  144.             break;
  145.  
  146.         default:
  147.             av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
  148.                 scratch[0], scratch[1],
  149.                 scratch[2], scratch[3]);
  150.             break;
  151.         }
  152.  
  153.         avio_skip(pb, chunk_size);
  154.     } while (chunk_tag != FINF_TAG);
  155.  
  156.     return 0;
  157. }
  158.  
  159. static int wsvqa_read_packet(AVFormatContext *s,
  160.                              AVPacket *pkt)
  161. {
  162.     WsVqaDemuxContext *wsvqa = s->priv_data;
  163.     AVIOContext *pb = s->pb;
  164.     int ret = -1;
  165.     uint8_t preamble[VQA_PREAMBLE_SIZE];
  166.     uint32_t chunk_type;
  167.     uint32_t chunk_size;
  168.     int skip_byte;
  169.  
  170.     while (avio_read(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) {
  171.         chunk_type = AV_RB32(&preamble[0]);
  172.         chunk_size = AV_RB32(&preamble[4]);
  173.  
  174.         skip_byte = chunk_size & 0x01;
  175.  
  176.         if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) ||
  177.             (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
  178.  
  179.             ret= av_get_packet(pb, pkt, chunk_size);
  180.             if (ret<0)
  181.                 return AVERROR(EIO);
  182.  
  183.             switch (chunk_type) {
  184.             case SND0_TAG:
  185.             case SND1_TAG:
  186.             case SND2_TAG:
  187.                 if (wsvqa->audio_stream_index == -1) {
  188.                     AVStream *st = avformat_new_stream(s, NULL);
  189.                     if (!st)
  190.                         return AVERROR(ENOMEM);
  191.  
  192.                     wsvqa->audio_stream_index = st->index;
  193.                     if (!wsvqa->sample_rate)
  194.                         wsvqa->sample_rate = 22050;
  195.                     if (!wsvqa->channels)
  196.                         wsvqa->channels = 1;
  197.                     if (!wsvqa->bps)
  198.                         wsvqa->bps = 8;
  199.                     st->codec->sample_rate = wsvqa->sample_rate;
  200.                     st->codec->bits_per_coded_sample = wsvqa->bps;
  201.                     st->codec->channels = wsvqa->channels;
  202.                     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  203.  
  204.                     avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
  205.  
  206.                     switch (chunk_type) {
  207.                     case SND0_TAG:
  208.                         if (wsvqa->bps == 16)
  209.                             st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
  210.                         else
  211.                             st->codec->codec_id = AV_CODEC_ID_PCM_U8;
  212.                         break;
  213.                     case SND1_TAG:
  214.                         st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
  215.                         break;
  216.                     case SND2_TAG:
  217.                         st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
  218.                         if (ff_alloc_extradata(st->codec, 2))
  219.                             return AVERROR(ENOMEM);
  220.                         AV_WL16(st->codec->extradata, wsvqa->version);
  221.                         break;
  222.                     }
  223.                 }
  224.  
  225.                 pkt->stream_index = wsvqa->audio_stream_index;
  226.                 switch (chunk_type) {
  227.                 case SND1_TAG:
  228.                     /* unpacked size is stored in header */
  229.                     if(pkt->data)
  230.                         pkt->duration = AV_RL16(pkt->data) / wsvqa->channels;
  231.                     break;
  232.                 case SND2_TAG:
  233.                     /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
  234.                     pkt->duration = (chunk_size * 2) / wsvqa->channels;
  235.                     break;
  236.                 }
  237.                 break;
  238.             case VQFR_TAG:
  239.                 pkt->stream_index = wsvqa->video_stream_index;
  240.                 pkt->duration = 1;
  241.                 break;
  242.             }
  243.  
  244.             /* stay on 16-bit alignment */
  245.             if (skip_byte)
  246.                 avio_skip(pb, 1);
  247.  
  248.             return ret;
  249.         } else {
  250.             switch(chunk_type){
  251.             case CMDS_TAG:
  252.                 break;
  253.             default:
  254.                 av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type);
  255.             }
  256.             avio_skip(pb, chunk_size + skip_byte);
  257.         }
  258.     }
  259.  
  260.     return ret;
  261. }
  262.  
  263. AVInputFormat ff_wsvqa_demuxer = {
  264.     .name           = "wsvqa",
  265.     .long_name      = NULL_IF_CONFIG_SMALL("Westwood Studios VQA"),
  266.     .priv_data_size = sizeof(WsVqaDemuxContext),
  267.     .read_probe     = wsvqa_probe,
  268.     .read_header    = wsvqa_read_header,
  269.     .read_packet    = wsvqa_read_packet,
  270. };
  271.