Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * 4X Technologies .4xm File Demuxer (no muxer)
  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.  * 4X Technologies file demuxer
  25.  * by Mike Melanson (melanson@pcisys.net)
  26.  * for more information on the .4xm file format, visit:
  27.  *   http://www.pcisys.net/~melanson/codecs/
  28.  */
  29.  
  30. #include "libavutil/intreadwrite.h"
  31. #include "libavutil/intfloat.h"
  32. #include "avformat.h"
  33. #include "internal.h"
  34.  
  35. #define     RIFF_TAG MKTAG('R', 'I', 'F', 'F')
  36. #define  FOURXMV_TAG MKTAG('4', 'X', 'M', 'V')
  37. #define     LIST_TAG MKTAG('L', 'I', 'S', 'T')
  38. #define     HEAD_TAG MKTAG('H', 'E', 'A', 'D')
  39. #define     TRK__TAG MKTAG('T', 'R', 'K', '_')
  40. #define     MOVI_TAG MKTAG('M', 'O', 'V', 'I')
  41. #define     VTRK_TAG MKTAG('V', 'T', 'R', 'K')
  42. #define     STRK_TAG MKTAG('S', 'T', 'R', 'K')
  43. #define     std__TAG MKTAG('s', 't', 'd', '_')
  44. #define     name_TAG MKTAG('n', 'a', 'm', 'e')
  45. #define     vtrk_TAG MKTAG('v', 't', 'r', 'k')
  46. #define     strk_TAG MKTAG('s', 't', 'r', 'k')
  47. #define     ifrm_TAG MKTAG('i', 'f', 'r', 'm')
  48. #define     pfrm_TAG MKTAG('p', 'f', 'r', 'm')
  49. #define     cfrm_TAG MKTAG('c', 'f', 'r', 'm')
  50. #define     ifr2_TAG MKTAG('i', 'f', 'r', '2')
  51. #define     pfr2_TAG MKTAG('p', 'f', 'r', '2')
  52. #define     cfr2_TAG MKTAG('c', 'f', 'r', '2')
  53. #define     snd__TAG MKTAG('s', 'n', 'd', '_')
  54.  
  55. #define vtrk_SIZE 0x44
  56. #define strk_SIZE 0x28
  57.  
  58. #define GET_LIST_HEADER() \
  59.     fourcc_tag = avio_rl32(pb); \
  60.     size       = avio_rl32(pb); \
  61.     if (fourcc_tag != LIST_TAG) \
  62.         return AVERROR_INVALIDDATA; \
  63.     fourcc_tag = avio_rl32(pb);
  64.  
  65. typedef struct AudioTrack {
  66.     int sample_rate;
  67.     int bits;
  68.     int channels;
  69.     int stream_index;
  70.     int adpcm;
  71.     int64_t audio_pts;
  72. } AudioTrack;
  73.  
  74. typedef struct FourxmDemuxContext {
  75.     int video_stream_index;
  76.     int track_count;
  77.     AudioTrack *tracks;
  78.  
  79.     int64_t video_pts;
  80.     AVRational fps;
  81. } FourxmDemuxContext;
  82.  
  83. static int fourxm_probe(AVProbeData *p)
  84. {
  85.     if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
  86.         (AV_RL32(&p->buf[8]) != FOURXMV_TAG))
  87.         return 0;
  88.  
  89.     return AVPROBE_SCORE_MAX;
  90. }
  91.  
  92. static int parse_vtrk(AVFormatContext *s,
  93.                       FourxmDemuxContext *fourxm, uint8_t *buf, int size,
  94.                       int left)
  95. {
  96.     AVStream *st;
  97.     /* check that there is enough data */
  98.     if (size != vtrk_SIZE || left < size + 8) {
  99.         return AVERROR_INVALIDDATA;
  100.     }
  101.  
  102.     /* allocate a new AVStream */
  103.     st = avformat_new_stream(s, NULL);
  104.     if (!st)
  105.         return AVERROR(ENOMEM);
  106.  
  107.     avpriv_set_pts_info(st, 60, fourxm->fps.den, fourxm->fps.num);
  108.  
  109.     fourxm->video_stream_index = st->index;
  110.  
  111.     st->codec->codec_type     = AVMEDIA_TYPE_VIDEO;
  112.     st->codec->codec_id       = AV_CODEC_ID_4XM;
  113.  
  114.     st->codec->extradata      = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE);
  115.     if (!st->codec->extradata)
  116.         return AVERROR(ENOMEM);
  117.     st->codec->extradata_size = 4;
  118.     AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
  119.     st->codec->width  = AV_RL32(buf + 36);
  120.     st->codec->height = AV_RL32(buf + 40);
  121.  
  122.     return 0;
  123. }
  124.  
  125.  
  126. static int parse_strk(AVFormatContext *s,
  127.                       FourxmDemuxContext *fourxm, uint8_t *buf, int size,
  128.                       int left)
  129. {
  130.     AVStream *st;
  131.     int track;
  132.     /* check that there is enough data */
  133.     if (size != strk_SIZE || left < size + 8)
  134.         return AVERROR_INVALIDDATA;
  135.  
  136.     track = AV_RL32(buf + 8);
  137.     if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
  138.         av_log(s, AV_LOG_ERROR, "current_track too large\n");
  139.         return AVERROR_INVALIDDATA;
  140.     }
  141.  
  142.     if (track + 1 > fourxm->track_count) {
  143.         if (av_reallocp_array(&fourxm->tracks, track + 1, sizeof(AudioTrack)))
  144.             return AVERROR(ENOMEM);
  145.         memset(&fourxm->tracks[fourxm->track_count], 0,
  146.                sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
  147.         fourxm->track_count = track + 1;
  148.     }
  149.     fourxm->tracks[track].adpcm       = AV_RL32(buf + 12);
  150.     fourxm->tracks[track].channels    = AV_RL32(buf + 36);
  151.     fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
  152.     fourxm->tracks[track].bits        = AV_RL32(buf + 44);
  153.     fourxm->tracks[track].audio_pts   = 0;
  154.  
  155.     if (fourxm->tracks[track].channels    <= 0 ||
  156.         fourxm->tracks[track].sample_rate <= 0 ||
  157.         fourxm->tracks[track].bits        <= 0) {
  158.         av_log(s, AV_LOG_ERROR, "audio header invalid\n");
  159.         return AVERROR_INVALIDDATA;
  160.     }
  161.     if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) {
  162.         av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
  163.         return AVERROR_INVALIDDATA;
  164.     }
  165.  
  166.     /* allocate a new AVStream */
  167.     st = avformat_new_stream(s, NULL);
  168.     if (!st)
  169.         return AVERROR(ENOMEM);
  170.  
  171.     st->id = track;
  172.     avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
  173.  
  174.     fourxm->tracks[track].stream_index = st->index;
  175.  
  176.     st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
  177.     st->codec->codec_tag             = 0;
  178.     st->codec->channels              = fourxm->tracks[track].channels;
  179.     st->codec->sample_rate           = fourxm->tracks[track].sample_rate;
  180.     st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
  181.     st->codec->bit_rate              = st->codec->channels *
  182.                                        st->codec->sample_rate *
  183.                                        st->codec->bits_per_coded_sample;
  184.     st->codec->block_align           = st->codec->channels *
  185.                                        st->codec->bits_per_coded_sample;
  186.  
  187.     if (fourxm->tracks[track].adpcm){
  188.         st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
  189.     } else if (st->codec->bits_per_coded_sample == 8) {
  190.         st->codec->codec_id = AV_CODEC_ID_PCM_U8;
  191.     } else
  192.         st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
  193.  
  194.     return 0;
  195. }
  196.  
  197. static int fourxm_read_header(AVFormatContext *s)
  198. {
  199.     AVIOContext *pb = s->pb;
  200.     unsigned int fourcc_tag;
  201.     unsigned int size;
  202.     int header_size;
  203.     FourxmDemuxContext *fourxm = s->priv_data;
  204.     unsigned char *header;
  205.     int i, ret;
  206.  
  207.     fourxm->track_count = 0;
  208.     fourxm->tracks      = NULL;
  209.     fourxm->fps         = (AVRational){1,1};
  210.  
  211.     /* skip the first 3 32-bit numbers */
  212.     avio_skip(pb, 12);
  213.  
  214.     /* check for LIST-HEAD */
  215.     GET_LIST_HEADER();
  216.     header_size = size - 4;
  217.     if (fourcc_tag != HEAD_TAG || header_size < 0)
  218.         return AVERROR_INVALIDDATA;
  219.  
  220.     /* allocate space for the header and load the whole thing */
  221.     header = av_malloc(header_size);
  222.     if (!header)
  223.         return AVERROR(ENOMEM);
  224.     if (avio_read(pb, header, header_size) != header_size) {
  225.         av_free(header);
  226.         return AVERROR(EIO);
  227.     }
  228.  
  229.     /* take the lazy approach and search for any and all vtrk and strk chunks */
  230.     for (i = 0; i < header_size - 8; i++) {
  231.         fourcc_tag = AV_RL32(&header[i]);
  232.         size       = AV_RL32(&header[i + 4]);
  233.         if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) {
  234.             av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8);
  235.             return AVERROR_INVALIDDATA;
  236.         }
  237.  
  238.         if (fourcc_tag == std__TAG) {
  239.             if (header_size - i < 16) {
  240.                 av_log(s, AV_LOG_ERROR, "std TAG truncated\n");
  241.                 ret = AVERROR_INVALIDDATA;
  242.                 goto fail;
  243.             }
  244.             fourxm->fps = av_d2q(av_int2float(AV_RL32(&header[i + 12])), 10000);
  245.         } else if (fourcc_tag == vtrk_TAG) {
  246.             if ((ret = parse_vtrk(s, fourxm, header + i, size,
  247.                                   header_size - i)) < 0)
  248.                 goto fail;
  249.  
  250.             i += 8 + size;
  251.         } else if (fourcc_tag == strk_TAG) {
  252.             if ((ret = parse_strk(s, fourxm, header + i, size,
  253.                                   header_size - i)) < 0)
  254.                 goto fail;
  255.  
  256.             i += 8 + size;
  257.         }
  258.     }
  259.  
  260.     /* skip over the LIST-MOVI chunk (which is where the stream should be */
  261.     GET_LIST_HEADER();
  262.     if (fourcc_tag != MOVI_TAG) {
  263.         ret = AVERROR_INVALIDDATA;
  264.         goto fail;
  265.     }
  266.  
  267.     av_free(header);
  268.     /* initialize context members */
  269.     fourxm->video_pts = -1;  /* first frame will push to 0 */
  270.  
  271.     return 0;
  272. fail:
  273.     av_freep(&fourxm->tracks);
  274.     av_free(header);
  275.     return ret;
  276. }
  277.  
  278. static int fourxm_read_packet(AVFormatContext *s,
  279.                               AVPacket *pkt)
  280. {
  281.     FourxmDemuxContext *fourxm = s->priv_data;
  282.     AVIOContext *pb            = s->pb;
  283.     unsigned int fourcc_tag;
  284.     unsigned int size;
  285.     int ret = 0;
  286.     unsigned int track_number;
  287.     int packet_read = 0;
  288.     unsigned char header[8];
  289.     int audio_frame_count;
  290.  
  291.     while (!packet_read) {
  292.         if ((ret = avio_read(s->pb, header, 8)) < 0)
  293.             return ret;
  294.         fourcc_tag = AV_RL32(&header[0]);
  295.         size       = AV_RL32(&header[4]);
  296.         if (avio_feof(pb))
  297.             return AVERROR(EIO);
  298.         switch (fourcc_tag) {
  299.         case LIST_TAG:
  300.             /* this is a good time to bump the video pts */
  301.             fourxm->video_pts++;
  302.  
  303.             /* skip the LIST-* tag and move on to the next fourcc */
  304.             avio_rl32(pb);
  305.             break;
  306.  
  307.         case ifrm_TAG:
  308.         case pfrm_TAG:
  309.         case cfrm_TAG:
  310.         case ifr2_TAG:
  311.         case pfr2_TAG:
  312.         case cfr2_TAG:
  313.             /* allocate 8 more bytes than 'size' to account for fourcc
  314.              * and size */
  315.             if (size + 8 < size || av_new_packet(pkt, size + 8))
  316.                 return AVERROR(EIO);
  317.             pkt->stream_index = fourxm->video_stream_index;
  318.             pkt->pts          = fourxm->video_pts;
  319.             pkt->pos          = avio_tell(s->pb);
  320.             memcpy(pkt->data, header, 8);
  321.             ret = avio_read(s->pb, &pkt->data[8], size);
  322.  
  323.             if (ret < 0) {
  324.                 av_free_packet(pkt);
  325.             } else {
  326.                 packet_read = 1;
  327.                 av_shrink_packet(pkt, ret + 8);
  328.             }
  329.             break;
  330.  
  331.         case snd__TAG:
  332.             track_number = avio_rl32(pb);
  333.             avio_skip(pb, 4);
  334.             size -= 8;
  335.  
  336.             if (track_number < fourxm->track_count &&
  337.                 fourxm->tracks[track_number].channels > 0) {
  338.                 ret = av_get_packet(s->pb, pkt, size);
  339.                 if (ret < 0)
  340.                     return AVERROR(EIO);
  341.                 pkt->stream_index =
  342.                     fourxm->tracks[track_number].stream_index;
  343.                 pkt->pts    = fourxm->tracks[track_number].audio_pts;
  344.                 packet_read = 1;
  345.  
  346.                 /* pts accounting */
  347.                 audio_frame_count = size;
  348.                 if (fourxm->tracks[track_number].adpcm)
  349.                     audio_frame_count -= 2 * (fourxm->tracks[track_number].channels);
  350.                 audio_frame_count /= fourxm->tracks[track_number].channels;
  351.                 if (fourxm->tracks[track_number].adpcm) {
  352.                     audio_frame_count *= 2;
  353.                 } else
  354.                     audio_frame_count /=
  355.                         (fourxm->tracks[track_number].bits / 8);
  356.                 fourxm->tracks[track_number].audio_pts += audio_frame_count;
  357.             } else {
  358.                 avio_skip(pb, size);
  359.             }
  360.             break;
  361.  
  362.         default:
  363.             avio_skip(pb, size);
  364.             break;
  365.         }
  366.     }
  367.     return ret;
  368. }
  369.  
  370. static int fourxm_read_close(AVFormatContext *s)
  371. {
  372.     FourxmDemuxContext *fourxm = s->priv_data;
  373.  
  374.     av_freep(&fourxm->tracks);
  375.  
  376.     return 0;
  377. }
  378.  
  379. AVInputFormat ff_fourxm_demuxer = {
  380.     .name           = "4xm",
  381.     .long_name      = NULL_IF_CONFIG_SMALL("4X Technologies"),
  382.     .priv_data_size = sizeof(FourxmDemuxContext),
  383.     .read_probe     = fourxm_probe,
  384.     .read_header    = fourxm_read_header,
  385.     .read_packet    = fourxm_read_packet,
  386.     .read_close     = fourxm_read_close,
  387. };
  388.