Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Sony Playstation (PSX) STR File 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.  * PSX STR file demuxer
  25.  * by Mike Melanson (melanson@pcisys.net)
  26.  * This module handles streams that have been ripped from Sony Playstation
  27.  * CD games. This demuxer can handle either raw STR files (which are just
  28.  * concatenations of raw compact disc sectors) or STR files with 0x2C-byte
  29.  * RIFF headers, followed by CD sectors.
  30.  */
  31.  
  32. #include "libavutil/channel_layout.h"
  33. #include "libavutil/internal.h"
  34. #include "libavutil/intreadwrite.h"
  35. #include "avformat.h"
  36. #include "internal.h"
  37.  
  38. #define RIFF_TAG MKTAG('R', 'I', 'F', 'F')
  39. #define CDXA_TAG MKTAG('C', 'D', 'X', 'A')
  40.  
  41. #define RAW_CD_SECTOR_SIZE      2352
  42. #define RAW_CD_SECTOR_DATA_SIZE 2304
  43. #define VIDEO_DATA_CHUNK_SIZE   0x7E0
  44. #define VIDEO_DATA_HEADER_SIZE  0x38
  45. #define RIFF_HEADER_SIZE        0x2C
  46.  
  47. #define CDXA_TYPE_MASK     0x0E
  48. #define CDXA_TYPE_DATA     0x08
  49. #define CDXA_TYPE_AUDIO    0x04
  50. #define CDXA_TYPE_VIDEO    0x02
  51.  
  52. #define STR_MAGIC (0x80010160)
  53.  
  54. typedef struct StrChannel {
  55.     /* video parameters */
  56.     int video_stream_index;
  57.     AVPacket tmp_pkt;
  58.  
  59.     /* audio parameters */
  60.     int audio_stream_index;
  61. } StrChannel;
  62.  
  63. typedef struct StrDemuxContext {
  64.  
  65.     /* a STR file can contain up to 32 channels of data */
  66.     StrChannel channels[32];
  67. } StrDemuxContext;
  68.  
  69. static const uint8_t sync_header[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
  70.  
  71. static int str_probe(AVProbeData *p)
  72. {
  73.     const uint8_t *sector= p->buf;
  74.     const uint8_t *end= sector + p->buf_size;
  75.     int aud=0, vid=0;
  76.  
  77.     if (p->buf_size < RAW_CD_SECTOR_SIZE)
  78.         return 0;
  79.  
  80.     if ((AV_RL32(&p->buf[0]) == RIFF_TAG) &&
  81.         (AV_RL32(&p->buf[8]) == CDXA_TAG)) {
  82.  
  83.         /* RIFF header seen; skip 0x2C bytes */
  84.         sector += RIFF_HEADER_SIZE;
  85.     }
  86.  
  87.     while (end - sector >= RAW_CD_SECTOR_SIZE) {
  88.         /* look for CD sync header (00, 0xFF x 10, 00) */
  89.         if (memcmp(sector,sync_header,sizeof(sync_header)))
  90.             return 0;
  91.  
  92.         if (sector[0x11] >= 32)
  93.             return 0;
  94.  
  95.         switch (sector[0x12] & CDXA_TYPE_MASK) {
  96.         case CDXA_TYPE_DATA:
  97.         case CDXA_TYPE_VIDEO: {
  98.                 int current_sector = AV_RL16(&sector[0x1C]);
  99.                 int sector_count   = AV_RL16(&sector[0x1E]);
  100.                 int frame_size = AV_RL32(&sector[0x24]);
  101.  
  102.                 if(!(   frame_size>=0
  103.                      && current_sector < sector_count
  104.                      && sector_count*VIDEO_DATA_CHUNK_SIZE >=frame_size)){
  105.                     return 0;
  106.                 }
  107.  
  108.                 /*st->codec->width      = AV_RL16(&sector[0x28]);
  109.                 st->codec->height     = AV_RL16(&sector[0x2A]);*/
  110.  
  111. //                 if (current_sector == sector_count-1) {
  112.                     vid++;
  113. //                 }
  114.  
  115.             }
  116.             break;
  117.         case CDXA_TYPE_AUDIO:
  118.             if(sector[0x13]&0x2A)
  119.                 return 0;
  120.             aud++;
  121.             break;
  122.         default:
  123.             if(sector[0x12] & CDXA_TYPE_MASK)
  124.                 return 0;
  125.         }
  126.         sector += RAW_CD_SECTOR_SIZE;
  127.     }
  128.     /* MPEG files (like those ripped from VCDs) can also look like this;
  129.      * only return half certainty */
  130.     if(vid+aud > 3)  return AVPROBE_SCORE_EXTENSION;
  131.     else if(vid+aud) return 1;
  132.     else             return 0;
  133. }
  134.  
  135. static int str_read_header(AVFormatContext *s)
  136. {
  137.     AVIOContext *pb = s->pb;
  138.     StrDemuxContext *str = s->priv_data;
  139.     unsigned char sector[RAW_CD_SECTOR_SIZE];
  140.     int start;
  141.     int i;
  142.  
  143.     /* skip over any RIFF header */
  144.     if (avio_read(pb, sector, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE)
  145.         return AVERROR(EIO);
  146.     if (AV_RL32(&sector[0]) == RIFF_TAG)
  147.         start = RIFF_HEADER_SIZE;
  148.     else
  149.         start = 0;
  150.  
  151.     avio_seek(pb, start, SEEK_SET);
  152.  
  153.     for(i=0; i<32; i++){
  154.         str->channels[i].video_stream_index=
  155.         str->channels[i].audio_stream_index= -1;
  156.     }
  157.  
  158.     s->ctx_flags |= AVFMTCTX_NOHEADER;
  159.  
  160.     return 0;
  161. }
  162.  
  163. static int str_read_packet(AVFormatContext *s,
  164.                            AVPacket *ret_pkt)
  165. {
  166.     AVIOContext *pb = s->pb;
  167.     StrDemuxContext *str = s->priv_data;
  168.     unsigned char sector[RAW_CD_SECTOR_SIZE];
  169.     int channel;
  170.     AVPacket *pkt;
  171.     AVStream *st;
  172.  
  173.     while (1) {
  174.  
  175.         if (avio_read(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
  176.             return AVERROR(EIO);
  177.  
  178.         channel = sector[0x11];
  179.         if (channel >= 32)
  180.             return AVERROR_INVALIDDATA;
  181.  
  182.         switch (sector[0x12] & CDXA_TYPE_MASK) {
  183.  
  184.         case CDXA_TYPE_DATA:
  185.         case CDXA_TYPE_VIDEO:
  186.             {
  187.  
  188.                 int current_sector = AV_RL16(&sector[0x1C]);
  189.                 int sector_count   = AV_RL16(&sector[0x1E]);
  190.                 int frame_size = AV_RL32(&sector[0x24]);
  191.  
  192.                 if(!(   frame_size>=0
  193.                      && current_sector < sector_count
  194.                      && sector_count*VIDEO_DATA_CHUNK_SIZE >=frame_size)){
  195.                     av_log(s, AV_LOG_ERROR, "Invalid parameters %d %d %d\n", current_sector, sector_count, frame_size);
  196.                     break;
  197.                 }
  198.  
  199.                 if(str->channels[channel].video_stream_index < 0){
  200.                     /* allocate a new AVStream */
  201.                     st = avformat_new_stream(s, NULL);
  202.                     if (!st)
  203.                         return AVERROR(ENOMEM);
  204.                     avpriv_set_pts_info(st, 64, 1, 15);
  205.  
  206.                     str->channels[channel].video_stream_index = st->index;
  207.  
  208.                     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  209.                     st->codec->codec_id   = AV_CODEC_ID_MDEC;
  210.                     st->codec->codec_tag  = 0;  /* no fourcc */
  211.                     st->codec->width      = AV_RL16(&sector[0x28]);
  212.                     st->codec->height     = AV_RL16(&sector[0x2A]);
  213.                 }
  214.  
  215.                 /* if this is the first sector of the frame, allocate a pkt */
  216.                 pkt = &str->channels[channel].tmp_pkt;
  217.  
  218.                 if(pkt->size != sector_count*VIDEO_DATA_CHUNK_SIZE){
  219.                     if(pkt->data)
  220.                         av_log(s, AV_LOG_ERROR, "missmatching sector_count\n");
  221.                     av_free_packet(pkt);
  222.                     if (av_new_packet(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE))
  223.                         return AVERROR(EIO);
  224.  
  225.                     pkt->pos= avio_tell(pb) - RAW_CD_SECTOR_SIZE;
  226.                     pkt->stream_index =
  227.                         str->channels[channel].video_stream_index;
  228.                 }
  229.  
  230.                 memcpy(pkt->data + current_sector*VIDEO_DATA_CHUNK_SIZE,
  231.                        sector + VIDEO_DATA_HEADER_SIZE,
  232.                        VIDEO_DATA_CHUNK_SIZE);
  233.  
  234.                 if (current_sector == sector_count-1) {
  235.                     pkt->size= frame_size;
  236.                     *ret_pkt = *pkt;
  237.                     pkt->data= NULL;
  238.                     pkt->size= -1;
  239.                     pkt->buf = NULL;
  240. #if FF_API_DESTRUCT_PACKET
  241. FF_DISABLE_DEPRECATION_WARNINGS
  242.                     pkt->destruct = NULL;
  243. FF_ENABLE_DEPRECATION_WARNINGS
  244. #endif
  245.                     return 0;
  246.                 }
  247.  
  248.             }
  249.             break;
  250.  
  251.         case CDXA_TYPE_AUDIO:
  252.             if(str->channels[channel].audio_stream_index < 0){
  253.                 int fmt = sector[0x13];
  254.                 /* allocate a new AVStream */
  255.                 st = avformat_new_stream(s, NULL);
  256.                 if (!st)
  257.                     return AVERROR(ENOMEM);
  258.  
  259.                 str->channels[channel].audio_stream_index = st->index;
  260.  
  261.                 st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
  262.                 st->codec->codec_id    = AV_CODEC_ID_ADPCM_XA;
  263.                 st->codec->codec_tag   = 0;  /* no fourcc */
  264.                 if (fmt & 1) {
  265.                     st->codec->channels       = 2;
  266.                     st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
  267.                 } else {
  268.                     st->codec->channels       = 1;
  269.                     st->codec->channel_layout = AV_CH_LAYOUT_MONO;
  270.                 }
  271.                 st->codec->sample_rate = (fmt&4)?18900:37800;
  272.             //    st->codec->bit_rate = 0; //FIXME;
  273.                 st->codec->block_align = 128;
  274.  
  275.                 avpriv_set_pts_info(st, 64, 18 * 224 / st->codec->channels,
  276.                                     st->codec->sample_rate);
  277.                 st->start_time = 0;
  278.             }
  279.             pkt = ret_pkt;
  280.             if (av_new_packet(pkt, 2304))
  281.                 return AVERROR(EIO);
  282.             memcpy(pkt->data,sector+24,2304);
  283.  
  284.             pkt->stream_index =
  285.                 str->channels[channel].audio_stream_index;
  286.             pkt->duration = 1;
  287.             return 0;
  288.         default:
  289.             av_log(s, AV_LOG_WARNING, "Unknown sector type %02X\n", sector[0x12]);
  290.             /* drop the sector and move on */
  291.             break;
  292.         }
  293.  
  294.         if (url_feof(pb))
  295.             return AVERROR(EIO);
  296.     }
  297. }
  298.  
  299. static int str_read_close(AVFormatContext *s)
  300. {
  301.     StrDemuxContext *str = s->priv_data;
  302.     int i;
  303.     for(i=0; i<32; i++){
  304.         if(str->channels[i].tmp_pkt.data)
  305.             av_free_packet(&str->channels[i].tmp_pkt);
  306.     }
  307.  
  308.     return 0;
  309. }
  310.  
  311. AVInputFormat ff_str_demuxer = {
  312.     .name           = "psxstr",
  313.     .long_name      = NULL_IF_CONFIG_SMALL("Sony Playstation STR"),
  314.     .priv_data_size = sizeof(StrDemuxContext),
  315.     .read_probe     = str_probe,
  316.     .read_header    = str_read_header,
  317.     .read_packet    = str_read_packet,
  318.     .read_close     = str_read_close,
  319.     .flags          = AVFMT_NO_BYTE_SEEK,
  320. };
  321.