Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Silicon Graphics Movie demuxer
  3.  * Copyright (c) 2012 Peter Ross
  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.  * Silicon Graphics Movie demuxer
  25.  */
  26.  
  27. #include "libavutil/eval.h"
  28. #include "libavutil/intreadwrite.h"
  29. #include "libavutil/rational.h"
  30. #include "avformat.h"
  31. #include "internal.h"
  32.  
  33. typedef struct {
  34.     int nb_video_tracks;
  35.     int nb_audio_tracks;
  36.  
  37.     int eof_count;        /**< number of streams that have finished */
  38.     int stream_index;     /**< current stream index */
  39.     int frame[2];         /**< frame nb for current stream */
  40. } MvContext;
  41.  
  42. #define AUDIO_FORMAT_SIGNED 401
  43.  
  44. static int mv_probe(AVProbeData *p)
  45. {
  46.     if (AV_RB32(p->buf) == MKBETAG('M','O','V','I') && AV_RB16(p->buf + 4) < 3)
  47.         return AVPROBE_SCORE_MAX;
  48.     return 0;
  49. }
  50.  
  51. static char * var_read_string(AVIOContext *pb, int size)
  52. {
  53.     char *str = av_malloc(size + 1);
  54.     int n;
  55.     if (!str)
  56.         return NULL;
  57.     n = avio_get_str(pb, size, str, size + 1);
  58.     if (n < size)
  59.          avio_skip(pb, size - n);
  60.     return str;
  61. }
  62.  
  63. static int var_read_int(AVIOContext *pb, int size)
  64. {
  65.     int v;
  66.     char * s = var_read_string(pb, size);
  67.     if (!s || sscanf(s, "%d", &v) != 1)
  68.         v = 0;
  69.     av_free(s);
  70.     return v;
  71. }
  72.  
  73. static AVRational var_read_float(AVIOContext *pb, int size)
  74. {
  75.     AVRational v;
  76.     char * s = var_read_string(pb, size);
  77.     if (!s)
  78.         return (AVRational){0, 0};
  79.     v = av_d2q(av_strtod(s, NULL), INT_MAX);
  80.     av_free(s);
  81.     return v;
  82. }
  83.  
  84. static void var_read_metadata(AVFormatContext *avctx, const char *tag, int size)
  85. {
  86.     char *value = var_read_string(avctx->pb, size);
  87.     if (value)
  88.         av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL);
  89. }
  90.  
  91. static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) {
  92.     if (channels <= 0) {
  93.         av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid\n", channels);
  94.         return AVERROR_INVALIDDATA;
  95.     }
  96.     st->codec->channels = channels;
  97.     st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
  98.     return 0;
  99. }
  100.  
  101. /**
  102.  * Parse global variable
  103.  * @return < 0 if unknown
  104.  */
  105. static int parse_global_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
  106. {
  107.     MvContext *mv = avctx->priv_data;
  108.     AVIOContext *pb = avctx->pb;
  109.     if (!strcmp(name, "__NUM_I_TRACKS")) {
  110.         mv->nb_video_tracks = var_read_int(pb, size);
  111.     } else if (!strcmp(name, "__NUM_A_TRACKS")) {
  112.         mv->nb_audio_tracks = var_read_int(pb, size);
  113.     } else if (!strcmp(name, "COMMENT") || !strcmp(name, "TITLE")) {
  114.         var_read_metadata(avctx, name, size);
  115.     } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") || !strcmp(name, "OPTIMIZED")) {
  116.         avio_skip(pb, size); // ignore
  117.     } else
  118.         return -1;
  119.  
  120.     return 0;
  121. }
  122.  
  123. /**
  124.  * Parse audio variable
  125.  * @return < 0 if unknown
  126.  */
  127. static int parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
  128. {
  129.     AVIOContext *pb = avctx->pb;
  130.     if (!strcmp(name, "__DIR_COUNT")) {
  131.         st->nb_frames = var_read_int(pb, size);
  132.     } else if (!strcmp(name, "AUDIO_FORMAT")) {
  133.         st->codec->codec_id = var_read_int(pb, size);
  134.     } else if (!strcmp(name, "COMPRESSION")) {
  135.         st->codec->codec_tag = var_read_int(pb, size);
  136.     } else if (!strcmp(name, "DEFAULT_VOL")) {
  137.         var_read_metadata(avctx, name, size);
  138.     } else if (!strcmp(name, "NUM_CHANNELS")) {
  139.         return set_channels(avctx, st, var_read_int(pb, size));
  140.     } else if (!strcmp(name, "SAMPLE_RATE")) {
  141.         st->codec->sample_rate = var_read_int(pb, size);
  142.         avpriv_set_pts_info(st, 33, 1, st->codec->sample_rate);
  143.     } else if (!strcmp(name, "SAMPLE_WIDTH")) {
  144.         st->codec->bits_per_coded_sample = var_read_int(pb, size) * 8;
  145.     } else
  146.         return -1;
  147.     return 0;
  148. }
  149.  
  150. /**
  151.  * Parse video variable
  152.  * @return < 0 if unknown
  153.  */
  154. static int parse_video_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)
  155. {
  156.     AVIOContext *pb = avctx->pb;
  157.     if (!strcmp(name, "__DIR_COUNT")) {
  158.         st->nb_frames = st->duration = var_read_int(pb, size);
  159.     } else if (!strcmp(name, "COMPRESSION")) {
  160.         char * str = var_read_string(pb, size);
  161.         if (!str)
  162.             return AVERROR_INVALIDDATA;
  163.         if (!strcmp(str, "1")) {
  164.             st->codec->codec_id = AV_CODEC_ID_MVC1;
  165.         } else if (!strcmp(str, "2")) {
  166.             st->codec->pix_fmt  = AV_PIX_FMT_ABGR;
  167.             st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
  168.         } else if (!strcmp(str, "3")) {
  169.             st->codec->codec_id = AV_CODEC_ID_SGIRLE;
  170.         } else if (!strcmp(str, "10")) {
  171.             st->codec->codec_id = AV_CODEC_ID_MJPEG;
  172.         } else if (!strcmp(str, "MVC2")) {
  173.             st->codec->codec_id = AV_CODEC_ID_MVC2;
  174.         } else {
  175.             avpriv_request_sample(avctx, "video compression %s", str);
  176.         }
  177.         av_free(str);
  178.     } else if (!strcmp(name, "FPS")) {
  179.         AVRational fps = var_read_float(pb, size);
  180.         avpriv_set_pts_info(st, 64, fps.den, fps.num);
  181.     } else if (!strcmp(name, "HEIGHT")) {
  182.         st->codec->height = var_read_int(pb, size);
  183.     } else if (!strcmp(name, "PIXEL_ASPECT")) {
  184.         st->sample_aspect_ratio = var_read_float(pb, size);
  185.         av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
  186.                   st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, INT_MAX);
  187.     } else if (!strcmp(name, "WIDTH")) {
  188.         st->codec->width = var_read_int(pb, size);
  189.     } else if (!strcmp(name, "ORIENTATION")) {
  190.         if (var_read_int(pb, size) == 1101) {
  191.             st->codec->extradata       = av_strdup("BottomUp");
  192.             st->codec->extradata_size  = 9;
  193.         }
  194.     } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) {
  195.         var_read_metadata(avctx, name, size);
  196.     } else if (!strcmp(name, "INTERLACING") || !strcmp(name, "PACKING")) {
  197.         avio_skip(pb, size); // ignore
  198.     } else
  199.         return -1;
  200.     return 0;
  201. }
  202.  
  203. static void read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size))
  204. {
  205.     int count, i;
  206.     AVIOContext *pb = avctx->pb;
  207.     avio_skip(pb, 4);
  208.     count = avio_rb32(pb);
  209.     avio_skip(pb, 4);
  210.     for (i = 0; i < count; i++) {
  211.         char name[17];
  212.         int size;
  213.         avio_read(pb, name, 16);
  214.         name[sizeof(name) - 1] = 0;
  215.         size = avio_rb32(pb);
  216.         if (parse(avctx, st, name, size) < 0) {
  217.             avpriv_request_sample(avctx, "variable %s", name);
  218.             avio_skip(pb, size);
  219.         }
  220.     }
  221. }
  222.  
  223. static void read_index(AVIOContext *pb, AVStream *st)
  224. {
  225.     uint64_t timestamp = 0;
  226.     int i;
  227.     for (i = 0; i < st->nb_frames; i++) {
  228.         uint32_t pos  = avio_rb32(pb);
  229.         uint32_t size = avio_rb32(pb);
  230.         avio_skip(pb, 8);
  231.         av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME);
  232.         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
  233.             timestamp += size / (st->codec->channels * 2);
  234.         } else {
  235.             timestamp++;
  236.         }
  237.     }
  238. }
  239.  
  240. static int mv_read_header(AVFormatContext *avctx)
  241. {
  242.     MvContext *mv = avctx->priv_data;
  243.     AVIOContext *pb = avctx->pb;
  244.     AVStream *ast = NULL, *vst = NULL; //initialization to suppress warning
  245.     int version, i;
  246.  
  247.     avio_skip(pb, 4);
  248.  
  249.     version = avio_rb16(pb);
  250.     if (version == 2) {
  251.         uint64_t timestamp;
  252.         int v;
  253.         avio_skip(pb, 22);
  254.  
  255.         /* allocate audio track first to prevent unnecessary seeking
  256.            (audio packet always precede video packet for a given frame) */
  257.         ast = avformat_new_stream(avctx, NULL);
  258.         if (!ast)
  259.             return AVERROR(ENOMEM);
  260.  
  261.         vst = avformat_new_stream(avctx, NULL);
  262.         if (!vst)
  263.             return AVERROR(ENOMEM);
  264.         vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  265.         avpriv_set_pts_info(vst, 64, 1, 15);
  266.         vst->nb_frames = avio_rb32(pb);
  267.         v = avio_rb32(pb);
  268.         switch (v) {
  269.         case 1:
  270.             vst->codec->codec_id = AV_CODEC_ID_MVC1;
  271.             break;
  272.         case 2:
  273.             vst->codec->pix_fmt  = AV_PIX_FMT_ARGB;
  274.             vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
  275.             break;
  276.         default:
  277.             avpriv_request_sample(avctx, "video compression %i", v);
  278.             break;
  279.         }
  280.         vst->codec->codec_tag = 0;
  281.         vst->codec->width     = avio_rb32(pb);
  282.         vst->codec->height    = avio_rb32(pb);
  283.         avio_skip(pb, 12);
  284.  
  285.         ast->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
  286.         ast->nb_frames             = vst->nb_frames;
  287.         ast->codec->sample_rate    = avio_rb32(pb);
  288.         avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate);
  289.         if (set_channels(avctx, ast, avio_rb32(pb)) < 0)
  290.             return AVERROR_INVALIDDATA;
  291.  
  292.         v = avio_rb32(pb);
  293.         if (v == AUDIO_FORMAT_SIGNED) {
  294.             ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
  295.         } else {
  296.             avpriv_request_sample(avctx, "audio compression (format %i)", v);
  297.         }
  298.  
  299.         avio_skip(pb, 12);
  300.         var_read_metadata(avctx, "title", 0x80);
  301.         var_read_metadata(avctx, "comment", 0x100);
  302.         avio_skip(pb, 0x80);
  303.  
  304.         timestamp = 0;
  305.         for (i = 0; i < vst->nb_frames; i++) {
  306.             uint32_t pos   = avio_rb32(pb);
  307.             uint32_t asize = avio_rb32(pb);
  308.             uint32_t vsize = avio_rb32(pb);
  309.             avio_skip(pb, 8);
  310.             av_add_index_entry(ast, pos,         timestamp, asize, 0, AVINDEX_KEYFRAME);
  311.             av_add_index_entry(vst, pos + asize, i,         vsize, 0, AVINDEX_KEYFRAME);
  312.             timestamp += asize / (ast->codec->channels * 2);
  313.         }
  314.     } else if (!version && avio_rb16(pb) == 3) {
  315.         avio_skip(pb, 4);
  316.  
  317.         read_table(avctx, NULL, parse_global_var);
  318.  
  319.         if (mv->nb_audio_tracks > 1) {
  320.             avpriv_request_sample(avctx, "multiple audio streams support");
  321.             return AVERROR_PATCHWELCOME;
  322.         } else if (mv->nb_audio_tracks) {
  323.             ast = avformat_new_stream(avctx, NULL);
  324.             if (!ast)
  325.                 return AVERROR(ENOMEM);
  326.             ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
  327.             /* temporarily store compression value in codec_tag; format value in codec_id */
  328.             read_table(avctx, ast, parse_audio_var);
  329.             if (ast->codec->codec_tag == 100 && ast->codec->codec_id == AUDIO_FORMAT_SIGNED && ast->codec->bits_per_coded_sample == 16) {
  330.                 ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
  331.             } else {
  332.                 avpriv_request_sample(avctx, "audio compression %i (format %i, width %i)",
  333.                     ast->codec->codec_tag, ast->codec->codec_id, ast->codec->bits_per_coded_sample);
  334.                 ast->codec->codec_id = AV_CODEC_ID_NONE;
  335.             }
  336.             ast->codec->codec_tag = 0;
  337.             if (ast->codec->channels <= 0) {
  338.                 av_log(avctx, AV_LOG_ERROR, "No valid channel count found\n");
  339.                 return AVERROR_INVALIDDATA;
  340.             }
  341.         }
  342.  
  343.         if (mv->nb_video_tracks > 1) {
  344.             avpriv_request_sample(avctx, "multiple video streams support");
  345.             return AVERROR_PATCHWELCOME;
  346.         } else if (mv->nb_video_tracks) {
  347.             vst = avformat_new_stream(avctx, NULL);
  348.             if (!vst)
  349.                 return AVERROR(ENOMEM);
  350.             vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  351.             read_table(avctx, vst, parse_video_var);
  352.         }
  353.  
  354.         if (mv->nb_audio_tracks)
  355.             read_index(pb, ast);
  356.  
  357.         if (mv->nb_video_tracks)
  358.             read_index(pb, vst);
  359.     } else {
  360.         avpriv_request_sample(avctx, "version %i", version);
  361.         return AVERROR_PATCHWELCOME;
  362.     }
  363.  
  364.     return 0;
  365. }
  366.  
  367. static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
  368. {
  369.     MvContext *mv = avctx->priv_data;
  370.     AVIOContext *pb = avctx->pb;
  371.     AVStream *st = avctx->streams[mv->stream_index];
  372.     const AVIndexEntry *index;
  373.     int frame = mv->frame[mv->stream_index];
  374.     int ret;
  375.     uint64_t pos;
  376.  
  377.     if (frame  < st->nb_index_entries) {
  378.         index = &st->index_entries[frame];
  379.         pos = avio_tell(pb);
  380.         if (index->pos > pos)
  381.             avio_skip(pb, index->pos - pos);
  382.         else if (index->pos < pos) {
  383.             if (!pb->seekable)
  384.                 return AVERROR(EIO);
  385.             ret = avio_seek(pb, index->pos, SEEK_SET);
  386.             if (ret < 0)
  387.                 return ret;
  388.         }
  389.         ret = av_get_packet(pb, pkt, index->size);
  390.         if (ret < 0)
  391.             return ret;
  392.  
  393.         pkt->stream_index = mv->stream_index;
  394.         pkt->pts = index->timestamp;
  395.         pkt->flags |= AV_PKT_FLAG_KEY;
  396.  
  397.         mv->frame[mv->stream_index]++;
  398.         mv->eof_count = 0;
  399.     } else {
  400.         mv->eof_count++;
  401.         if (mv->eof_count >= avctx->nb_streams)
  402.             return AVERROR_EOF;
  403.     }
  404.  
  405.     mv->stream_index++;
  406.     if (mv->stream_index >= avctx->nb_streams)
  407.         mv->stream_index = 0;
  408.  
  409.     return 0;
  410. }
  411.  
  412. static int mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
  413. {
  414.     MvContext *mv = avctx->priv_data;
  415.     AVStream *st = avctx->streams[stream_index];
  416.     int frame, i;
  417.  
  418.     if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
  419.         return AVERROR(ENOSYS);
  420.  
  421.     if (!avctx->pb->seekable)
  422.         return AVERROR(EIO);
  423.  
  424.     frame = av_index_search_timestamp(st, timestamp, flags);
  425.     if (frame < 0)
  426.         return -1;
  427.  
  428.     for (i = 0; i < avctx->nb_streams; i++)
  429.         mv->frame[i] = frame;
  430.     return 0;
  431. }
  432.  
  433. AVInputFormat ff_mv_demuxer = {
  434.     .name           = "mv",
  435.     .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics Movie"),
  436.     .priv_data_size = sizeof(MvContext),
  437.     .read_probe     = mv_probe,
  438.     .read_header    = mv_read_header,
  439.     .read_packet    = mv_read_packet,
  440.     .read_seek      = mv_read_seek,
  441. };
  442.