Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * ARMovie/RPL demuxer
  3.  * Copyright (c) 2007 Christian Ohm, 2008 Eli Friedman
  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. #include <inttypes.h>
  23. #include <stdlib.h>
  24.  
  25. #include "libavutil/avstring.h"
  26. #include "libavutil/dict.h"
  27. #include "avformat.h"
  28. #include "internal.h"
  29.  
  30. #define RPL_SIGNATURE "ARMovie\x0A"
  31. #define RPL_SIGNATURE_SIZE 8
  32.  
  33. /** 256 is arbitrary, but should be big enough for any reasonable file. */
  34. #define RPL_LINE_LENGTH 256
  35.  
  36. static int rpl_probe(AVProbeData *p)
  37. {
  38.     if (memcmp(p->buf, RPL_SIGNATURE, RPL_SIGNATURE_SIZE))
  39.         return 0;
  40.  
  41.     return AVPROBE_SCORE_MAX;
  42. }
  43.  
  44. typedef struct RPLContext {
  45.     // RPL header data
  46.     int32_t frames_per_chunk;
  47.  
  48.     // Stream position data
  49.     uint32_t chunk_number;
  50.     uint32_t chunk_part;
  51.     uint32_t frame_in_part;
  52. } RPLContext;
  53.  
  54. static int read_line(AVIOContext * pb, char* line, int bufsize)
  55. {
  56.     int i;
  57.     for (i = 0; i < bufsize - 1; i++) {
  58.         int b = avio_r8(pb);
  59.         if (b == 0)
  60.             break;
  61.         if (b == '\n') {
  62.             line[i] = '\0';
  63.             return avio_feof(pb) ? -1 : 0;
  64.         }
  65.         line[i] = b;
  66.     }
  67.     line[i] = '\0';
  68.     return -1;
  69. }
  70.  
  71. static int32_t read_int(const char* line, const char** endptr, int* error)
  72. {
  73.     unsigned long result = 0;
  74.     for (; *line>='0' && *line<='9'; line++) {
  75.         if (result > (0x7FFFFFFF - 9) / 10)
  76.             *error = -1;
  77.         result = 10 * result + *line - '0';
  78.     }
  79.     *endptr = line;
  80.     return result;
  81. }
  82.  
  83. static int32_t read_line_and_int(AVIOContext * pb, int* error)
  84. {
  85.     char line[RPL_LINE_LENGTH];
  86.     const char *endptr;
  87.     *error |= read_line(pb, line, sizeof(line));
  88.     return read_int(line, &endptr, error);
  89. }
  90.  
  91. /** Parsing for fps, which can be a fraction. Unfortunately,
  92.   * the spec for the header leaves out a lot of details,
  93.   * so this is mostly guessing.
  94.   */
  95. static AVRational read_fps(const char* line, int* error)
  96. {
  97.     int64_t num, den = 1;
  98.     AVRational result;
  99.     num = read_int(line, &line, error);
  100.     if (*line == '.')
  101.         line++;
  102.     for (; *line>='0' && *line<='9'; line++) {
  103.         // Truncate any numerator too large to fit into an int64_t
  104.         if (num > (INT64_MAX - 9) / 10 || den > INT64_MAX / 10)
  105.             break;
  106.         num  = 10 * num + *line - '0';
  107.         den *= 10;
  108.     }
  109.     if (!num)
  110.         *error = -1;
  111.     av_reduce(&result.num, &result.den, num, den, 0x7FFFFFFF);
  112.     return result;
  113. }
  114.  
  115. static int rpl_read_header(AVFormatContext *s)
  116. {
  117.     AVIOContext *pb = s->pb;
  118.     RPLContext *rpl = s->priv_data;
  119.     AVStream *vst = NULL, *ast = NULL;
  120.     int total_audio_size;
  121.     int error = 0;
  122.  
  123.     uint32_t i;
  124.  
  125.     int32_t audio_format, chunk_catalog_offset, number_of_chunks;
  126.     AVRational fps;
  127.  
  128.     char line[RPL_LINE_LENGTH];
  129.  
  130.     // The header for RPL/ARMovie files is 21 lines of text
  131.     // containing the various header fields.  The fields are always
  132.     // in the same order, and other text besides the first
  133.     // number usually isn't important.
  134.     // (The spec says that there exists some significance
  135.     // for the text in a few cases; samples needed.)
  136.     error |= read_line(pb, line, sizeof(line));      // ARMovie
  137.     error |= read_line(pb, line, sizeof(line));      // movie name
  138.     av_dict_set(&s->metadata, "title"    , line, 0);
  139.     error |= read_line(pb, line, sizeof(line));      // date/copyright
  140.     av_dict_set(&s->metadata, "copyright", line, 0);
  141.     error |= read_line(pb, line, sizeof(line));      // author and other
  142.     av_dict_set(&s->metadata, "author"   , line, 0);
  143.  
  144.     // video headers
  145.     vst = avformat_new_stream(s, NULL);
  146.     if (!vst)
  147.         return AVERROR(ENOMEM);
  148.     vst->codec->codec_type      = AVMEDIA_TYPE_VIDEO;
  149.     vst->codec->codec_tag       = read_line_and_int(pb, &error);  // video format
  150.     vst->codec->width           = read_line_and_int(pb, &error);  // video width
  151.     vst->codec->height          = read_line_and_int(pb, &error);  // video height
  152.     vst->codec->bits_per_coded_sample = read_line_and_int(pb, &error);  // video bits per sample
  153.     error |= read_line(pb, line, sizeof(line));                   // video frames per second
  154.     fps = read_fps(line, &error);
  155.     avpriv_set_pts_info(vst, 32, fps.den, fps.num);
  156.  
  157.     // Figure out the video codec
  158.     switch (vst->codec->codec_tag) {
  159. #if 0
  160.         case 122:
  161.             vst->codec->codec_id = AV_CODEC_ID_ESCAPE122;
  162.             break;
  163. #endif
  164.         case 124:
  165.             vst->codec->codec_id = AV_CODEC_ID_ESCAPE124;
  166.             // The header is wrong here, at least sometimes
  167.             vst->codec->bits_per_coded_sample = 16;
  168.             break;
  169.         case 130:
  170.             vst->codec->codec_id = AV_CODEC_ID_ESCAPE130;
  171.             break;
  172.         default:
  173.             avpriv_report_missing_feature(s, "Video format %i",
  174.                                           vst->codec->codec_tag);
  175.             vst->codec->codec_id = AV_CODEC_ID_NONE;
  176.     }
  177.  
  178.     // Audio headers
  179.  
  180.     // ARMovie supports multiple audio tracks; I don't have any
  181.     // samples, though. This code will ignore additional tracks.
  182.     audio_format = read_line_and_int(pb, &error);  // audio format ID
  183.     if (audio_format) {
  184.         ast = avformat_new_stream(s, NULL);
  185.         if (!ast)
  186.             return AVERROR(ENOMEM);
  187.         ast->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
  188.         ast->codec->codec_tag       = audio_format;
  189.         ast->codec->sample_rate     = read_line_and_int(pb, &error);  // audio bitrate
  190.         ast->codec->channels        = read_line_and_int(pb, &error);  // number of audio channels
  191.         ast->codec->bits_per_coded_sample = read_line_and_int(pb, &error);  // audio bits per sample
  192.         // At least one sample uses 0 for ADPCM, which is really 4 bits
  193.         // per sample.
  194.         if (ast->codec->bits_per_coded_sample == 0)
  195.             ast->codec->bits_per_coded_sample = 4;
  196.  
  197.         ast->codec->bit_rate = ast->codec->sample_rate *
  198.                                ast->codec->bits_per_coded_sample *
  199.                                ast->codec->channels;
  200.  
  201.         ast->codec->codec_id = AV_CODEC_ID_NONE;
  202.         switch (audio_format) {
  203.             case 1:
  204.                 if (ast->codec->bits_per_coded_sample == 16) {
  205.                     // 16-bit audio is always signed
  206.                     ast->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
  207.                     break;
  208.                 }
  209.                 // There are some other formats listed as legal per the spec;
  210.                 // samples needed.
  211.                 break;
  212.             case 101:
  213.                 if (ast->codec->bits_per_coded_sample == 8) {
  214.                     // The samples with this kind of audio that I have
  215.                     // are all unsigned.
  216.                     ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
  217.                     break;
  218.                 } else if (ast->codec->bits_per_coded_sample == 4) {
  219.                     ast->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD;
  220.                     break;
  221.                 }
  222.                 break;
  223.         }
  224.         if (ast->codec->codec_id == AV_CODEC_ID_NONE)
  225.             avpriv_request_sample(s, "Audio format %"PRId32,
  226.                                   audio_format);
  227.         avpriv_set_pts_info(ast, 32, 1, ast->codec->bit_rate);
  228.     } else {
  229.         for (i = 0; i < 3; i++)
  230.             error |= read_line(pb, line, sizeof(line));
  231.     }
  232.  
  233.     rpl->frames_per_chunk = read_line_and_int(pb, &error);  // video frames per chunk
  234.     if (rpl->frames_per_chunk > 1 && vst->codec->codec_tag != 124)
  235.         av_log(s, AV_LOG_WARNING,
  236.                "Don't know how to split frames for video format %i. "
  237.                "Video stream will be broken!\n", vst->codec->codec_tag);
  238.  
  239.     number_of_chunks = read_line_and_int(pb, &error);  // number of chunks in the file
  240.     // The number in the header is actually the index of the last chunk.
  241.     number_of_chunks++;
  242.  
  243.     error |= read_line(pb, line, sizeof(line));  // "even" chunk size in bytes
  244.     error |= read_line(pb, line, sizeof(line));  // "odd" chunk size in bytes
  245.     chunk_catalog_offset =                       // offset of the "chunk catalog"
  246.         read_line_and_int(pb, &error);           //   (file index)
  247.     error |= read_line(pb, line, sizeof(line));  // offset to "helpful" sprite
  248.     error |= read_line(pb, line, sizeof(line));  // size of "helpful" sprite
  249.     error |= read_line(pb, line, sizeof(line));  // offset to key frame list
  250.  
  251.     // Read the index
  252.     avio_seek(pb, chunk_catalog_offset, SEEK_SET);
  253.     total_audio_size = 0;
  254.     for (i = 0; !error && i < number_of_chunks; i++) {
  255.         int64_t offset, video_size, audio_size;
  256.         error |= read_line(pb, line, sizeof(line));
  257.         if (3 != sscanf(line, "%"SCNd64" , %"SCNd64" ; %"SCNd64,
  258.                         &offset, &video_size, &audio_size)) {
  259.             error = -1;
  260.             continue;
  261.         }
  262.         av_add_index_entry(vst, offset, i * rpl->frames_per_chunk,
  263.                            video_size, rpl->frames_per_chunk, 0);
  264.         if (ast)
  265.             av_add_index_entry(ast, offset + video_size, total_audio_size,
  266.                                audio_size, audio_size * 8, 0);
  267.         total_audio_size += audio_size * 8;
  268.     }
  269.  
  270.     if (error) return AVERROR(EIO);
  271.  
  272.     return 0;
  273. }
  274.  
  275. static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt)
  276. {
  277.     RPLContext *rpl = s->priv_data;
  278.     AVIOContext *pb = s->pb;
  279.     AVStream* stream;
  280.     AVIndexEntry* index_entry;
  281.     int ret;
  282.  
  283.     if (rpl->chunk_part == s->nb_streams) {
  284.         rpl->chunk_number++;
  285.         rpl->chunk_part = 0;
  286.     }
  287.  
  288.     stream = s->streams[rpl->chunk_part];
  289.  
  290.     if (rpl->chunk_number >= stream->nb_index_entries)
  291.         return AVERROR_EOF;
  292.  
  293.     index_entry = &stream->index_entries[rpl->chunk_number];
  294.  
  295.     if (rpl->frame_in_part == 0)
  296.         if (avio_seek(pb, index_entry->pos, SEEK_SET) < 0)
  297.             return AVERROR(EIO);
  298.  
  299.     if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
  300.         stream->codec->codec_tag == 124) {
  301.         // We have to split Escape 124 frames because there are
  302.         // multiple frames per chunk in Escape 124 samples.
  303.         uint32_t frame_size;
  304.  
  305.         avio_skip(pb, 4); /* flags */
  306.         frame_size = avio_rl32(pb);
  307.         if (avio_seek(pb, -8, SEEK_CUR) < 0)
  308.             return AVERROR(EIO);
  309.  
  310.         ret = av_get_packet(pb, pkt, frame_size);
  311.         if (ret < 0)
  312.             return ret;
  313.         if (ret != frame_size) {
  314.             av_free_packet(pkt);
  315.             return AVERROR(EIO);
  316.         }
  317.         pkt->duration = 1;
  318.         pkt->pts = index_entry->timestamp + rpl->frame_in_part;
  319.         pkt->stream_index = rpl->chunk_part;
  320.  
  321.         rpl->frame_in_part++;
  322.         if (rpl->frame_in_part == rpl->frames_per_chunk) {
  323.             rpl->frame_in_part = 0;
  324.             rpl->chunk_part++;
  325.         }
  326.     } else {
  327.         ret = av_get_packet(pb, pkt, index_entry->size);
  328.         if (ret < 0)
  329.             return ret;
  330.         if (ret != index_entry->size) {
  331.             av_free_packet(pkt);
  332.             return AVERROR(EIO);
  333.         }
  334.  
  335.         if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  336.             // frames_per_chunk should always be one here; the header
  337.             // parsing will warn if it isn't.
  338.             pkt->duration = rpl->frames_per_chunk;
  339.         } else {
  340.             // All the audio codecs supported in this container
  341.             // (at least so far) are constant-bitrate.
  342.             pkt->duration = ret * 8;
  343.         }
  344.         pkt->pts = index_entry->timestamp;
  345.         pkt->stream_index = rpl->chunk_part;
  346.         rpl->chunk_part++;
  347.     }
  348.  
  349.     // None of the Escape formats have keyframes, and the ADPCM
  350.     // format used doesn't have keyframes.
  351.     if (rpl->chunk_number == 0 && rpl->frame_in_part == 0)
  352.         pkt->flags |= AV_PKT_FLAG_KEY;
  353.  
  354.     return ret;
  355. }
  356.  
  357. AVInputFormat ff_rpl_demuxer = {
  358.     .name           = "rpl",
  359.     .long_name      = NULL_IF_CONFIG_SMALL("RPL / ARMovie"),
  360.     .priv_data_size = sizeof(RPLContext),
  361.     .read_probe     = rpl_probe,
  362.     .read_header    = rpl_read_header,
  363.     .read_packet    = rpl_read_packet,
  364. };
  365.