Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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.     float 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, 1, fourxm->fps);
  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.     st->codec->extradata_size = 4;
  114.     st->codec->extradata      = av_malloc(4);
  115.     AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
  116.     st->codec->width  = AV_RL32(buf + 36);
  117.     st->codec->height = AV_RL32(buf + 40);
  118.  
  119.     return 0;
  120. }
  121.  
  122.  
  123. static int parse_strk(AVFormatContext *s,
  124.                       FourxmDemuxContext *fourxm, uint8_t *buf, int size,
  125.                       int left)
  126. {
  127.     AVStream *st;
  128.     int track;
  129.     /* check that there is enough data */
  130.     if (size != strk_SIZE || left < size + 8)
  131.         return AVERROR_INVALIDDATA;
  132.  
  133.     track = AV_RL32(buf + 8);
  134.     if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
  135.         av_log(s, AV_LOG_ERROR, "current_track too large\n");
  136.         return AVERROR_INVALIDDATA;
  137.     }
  138.  
  139.     if (track + 1 > fourxm->track_count) {
  140.         if (av_reallocp_array(&fourxm->tracks, track + 1, sizeof(AudioTrack)))
  141.             return AVERROR(ENOMEM);
  142.         memset(&fourxm->tracks[fourxm->track_count], 0,
  143.                sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
  144.         fourxm->track_count = track + 1;
  145.     }
  146.     fourxm->tracks[track].adpcm       = AV_RL32(buf + 12);
  147.     fourxm->tracks[track].channels    = AV_RL32(buf + 36);
  148.     fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
  149.     fourxm->tracks[track].bits        = AV_RL32(buf + 44);
  150.     fourxm->tracks[track].audio_pts   = 0;
  151.  
  152.     if (fourxm->tracks[track].channels    <= 0 ||
  153.         fourxm->tracks[track].sample_rate <= 0 ||
  154.         fourxm->tracks[track].bits        <= 0) {
  155.         av_log(s, AV_LOG_ERROR, "audio header invalid\n");
  156.         return AVERROR_INVALIDDATA;
  157.     }
  158.     if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) {
  159.         av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
  160.         return AVERROR_INVALIDDATA;
  161.     }
  162.  
  163.     /* allocate a new AVStream */
  164.     st = avformat_new_stream(s, NULL);
  165.     if (!st)
  166.         return AVERROR(ENOMEM);
  167.  
  168.     st->id = track;
  169.     avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
  170.  
  171.     fourxm->tracks[track].stream_index = st->index;
  172.  
  173.     st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
  174.     st->codec->codec_tag             = 0;
  175.     st->codec->channels              = fourxm->tracks[track].channels;
  176.     st->codec->sample_rate           = fourxm->tracks[track].sample_rate;
  177.     st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
  178.     st->codec->bit_rate              = st->codec->channels *
  179.                                        st->codec->sample_rate *
  180.                                        st->codec->bits_per_coded_sample;
  181.     st->codec->block_align           = st->codec->channels *
  182.                                        st->codec->bits_per_coded_sample;
  183.  
  184.     if (fourxm->tracks[track].adpcm){
  185.         st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
  186.     } else if (st->codec->bits_per_coded_sample == 8) {
  187.         st->codec->codec_id = AV_CODEC_ID_PCM_U8;
  188.     } else
  189.         st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
  190.  
  191.     return 0;
  192. }
  193.  
  194. static int fourxm_read_header(AVFormatContext *s)
  195. {
  196.     AVIOContext *pb = s->pb;
  197.     unsigned int fourcc_tag;
  198.     unsigned int size;
  199.     int header_size;
  200.     FourxmDemuxContext *fourxm = s->priv_data;
  201.     unsigned char *header;
  202.     int i, ret;
  203.  
  204.     fourxm->track_count = 0;
  205.     fourxm->tracks      = NULL;
  206.     fourxm->fps         = 1.0;
  207.  
  208.     /* skip the first 3 32-bit numbers */
  209.     avio_skip(pb, 12);
  210.  
  211.     /* check for LIST-HEAD */
  212.     GET_LIST_HEADER();
  213.     header_size = size - 4;
  214.     if (fourcc_tag != HEAD_TAG || header_size < 0)
  215.         return AVERROR_INVALIDDATA;
  216.  
  217.     /* allocate space for the header and load the whole thing */
  218.     header = av_malloc(header_size);
  219.     if (!header)
  220.         return AVERROR(ENOMEM);
  221.     if (avio_read(pb, header, header_size) != header_size) {
  222.         av_free(header);
  223.         return AVERROR(EIO);
  224.     }
  225.  
  226.     /* take the lazy approach and search for any and all vtrk and strk chunks */
  227.     for (i = 0; i < header_size - 8; i++) {
  228.         fourcc_tag = AV_RL32(&header[i]);
  229.         size       = AV_RL32(&header[i + 4]);
  230.         if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) {
  231.             av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8);
  232.             return AVERROR_INVALIDDATA;
  233.         }
  234.  
  235.         if (fourcc_tag == std__TAG) {
  236.             if (header_size - i < 16) {
  237.                 av_log(s, AV_LOG_ERROR, "std TAG truncated\n");
  238.                 ret = AVERROR_INVALIDDATA;
  239.                 goto fail;
  240.             }
  241.             fourxm->fps = av_int2float(AV_RL32(&header[i + 12]));
  242.         } else if (fourcc_tag == vtrk_TAG) {
  243.             if ((ret = parse_vtrk(s, fourxm, header + i, size,
  244.                                   header_size - i)) < 0)
  245.                 goto fail;
  246.  
  247.             i += 8 + size;
  248.         } else if (fourcc_tag == strk_TAG) {
  249.             if ((ret = parse_strk(s, fourxm, header + i, size,
  250.                                   header_size - i)) < 0)
  251.                 goto fail;
  252.  
  253.             i += 8 + size;
  254.         }
  255.     }
  256.  
  257.     /* skip over the LIST-MOVI chunk (which is where the stream should be */
  258.     GET_LIST_HEADER();
  259.     if (fourcc_tag != MOVI_TAG) {
  260.         ret = AVERROR_INVALIDDATA;
  261.         goto fail;
  262.     }
  263.  
  264.     av_free(header);
  265.     /* initialize context members */
  266.     fourxm->video_pts = -1;  /* first frame will push to 0 */
  267.  
  268.     return 0;
  269. fail:
  270.     av_freep(&fourxm->tracks);
  271.     av_free(header);
  272.     return ret;
  273. }
  274.  
  275. static int fourxm_read_packet(AVFormatContext *s,
  276.                               AVPacket *pkt)
  277. {
  278.     FourxmDemuxContext *fourxm = s->priv_data;
  279.     AVIOContext *pb            = s->pb;
  280.     unsigned int fourcc_tag;
  281.     unsigned int size;
  282.     int ret = 0;
  283.     unsigned int track_number;
  284.     int packet_read = 0;
  285.     unsigned char header[8];
  286.     int audio_frame_count;
  287.  
  288.     while (!packet_read) {
  289.         if ((ret = avio_read(s->pb, header, 8)) < 0)
  290.             return ret;
  291.         fourcc_tag = AV_RL32(&header[0]);
  292.         size       = AV_RL32(&header[4]);
  293.         if (url_feof(pb))
  294.             return AVERROR(EIO);
  295.         switch (fourcc_tag) {
  296.         case LIST_TAG:
  297.             /* this is a good time to bump the video pts */
  298.             fourxm->video_pts++;
  299.  
  300.             /* skip the LIST-* tag and move on to the next fourcc */
  301.             avio_rl32(pb);
  302.             break;
  303.  
  304.         case ifrm_TAG:
  305.         case pfrm_TAG:
  306.         case cfrm_TAG:
  307.         case ifr2_TAG:
  308.         case pfr2_TAG:
  309.         case cfr2_TAG:
  310.             /* allocate 8 more bytes than 'size' to account for fourcc
  311.              * and size */
  312.             if (size + 8 < size || av_new_packet(pkt, size + 8))
  313.                 return AVERROR(EIO);
  314.             pkt->stream_index = fourxm->video_stream_index;
  315.             pkt->pts          = fourxm->video_pts;
  316.             pkt->pos          = avio_tell(s->pb);
  317.             memcpy(pkt->data, header, 8);
  318.             ret = avio_read(s->pb, &pkt->data[8], size);
  319.  
  320.             if (ret < 0) {
  321.                 av_free_packet(pkt);
  322.             } else
  323.                 packet_read = 1;
  324.             break;
  325.  
  326.         case snd__TAG:
  327.             track_number = avio_rl32(pb);
  328.             avio_skip(pb, 4);
  329.             size -= 8;
  330.  
  331.             if (track_number < fourxm->track_count &&
  332.                 fourxm->tracks[track_number].channels > 0) {
  333.                 ret = av_get_packet(s->pb, pkt, size);
  334.                 if (ret < 0)
  335.                     return AVERROR(EIO);
  336.                 pkt->stream_index =
  337.                     fourxm->tracks[track_number].stream_index;
  338.                 pkt->pts    = fourxm->tracks[track_number].audio_pts;
  339.                 packet_read = 1;
  340.  
  341.                 /* pts accounting */
  342.                 audio_frame_count = size;
  343.                 if (fourxm->tracks[track_number].adpcm)
  344.                     audio_frame_count -= 2 * (fourxm->tracks[track_number].channels);
  345.                 audio_frame_count /= fourxm->tracks[track_number].channels;
  346.                 if (fourxm->tracks[track_number].adpcm) {
  347.                     audio_frame_count *= 2;
  348.                 } else
  349.                     audio_frame_count /=
  350.                         (fourxm->tracks[track_number].bits / 8);
  351.                 fourxm->tracks[track_number].audio_pts += audio_frame_count;
  352.             } else {
  353.                 avio_skip(pb, size);
  354.             }
  355.             break;
  356.  
  357.         default:
  358.             avio_skip(pb, size);
  359.             break;
  360.         }
  361.     }
  362.     return ret;
  363. }
  364.  
  365. static int fourxm_read_close(AVFormatContext *s)
  366. {
  367.     FourxmDemuxContext *fourxm = s->priv_data;
  368.  
  369.     av_freep(&fourxm->tracks);
  370.  
  371.     return 0;
  372. }
  373.  
  374. AVInputFormat ff_fourxm_demuxer = {
  375.     .name           = "4xm",
  376.     .long_name      = NULL_IF_CONFIG_SMALL("4X Technologies"),
  377.     .priv_data_size = sizeof(FourxmDemuxContext),
  378.     .read_probe     = fourxm_probe,
  379.     .read_header    = fourxm_read_header,
  380.     .read_packet    = fourxm_read_packet,
  381.     .read_close     = fourxm_read_close,
  382. };
  383.