1/* 2 * RL2 Format Demuxer 3 * Copyright (c) 2008 Sascha Sommer (saschasommer@freenet.de) 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * RL2 file demuxer 24 * @file 25 * @author Sascha Sommer (saschasommer@freenet.de) 26 * @see http://wiki.multimedia.cx/index.php?title=RL2 27 * 28 * extradata: 29 * 2 byte le initial drawing offset within 320x200 viewport 30 * 4 byte le number of used colors 31 * 256 * 3 bytes rgb palette 32 * optional background_frame 33 */ 34 35#include "libavutil/intreadwrite.h" 36#include "libavutil/mathematics.h" 37#include "avformat.h" 38#include "internal.h" 39 40#define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr, palette 41 42#define FORM_TAG MKBETAG('F', 'O', 'R', 'M') 43#define RLV2_TAG MKBETAG('R', 'L', 'V', '2') 44#define RLV3_TAG MKBETAG('R', 'L', 'V', '3') 45 46typedef struct Rl2DemuxContext { 47 unsigned int index_pos[2]; ///< indexes in the sample tables 48} Rl2DemuxContext; 49 50 51/** 52 * check if the file is in rl2 format 53 * @param p probe buffer 54 * @return 0 when the probe buffer does not contain rl2 data, > 0 otherwise 55 */ 56static int rl2_probe(AVProbeData *p) 57{ 58 59 if(AV_RB32(&p->buf[0]) != FORM_TAG) 60 return 0; 61 62 if(AV_RB32(&p->buf[8]) != RLV2_TAG && 63 AV_RB32(&p->buf[8]) != RLV3_TAG) 64 return 0; 65 66 return AVPROBE_SCORE_MAX; 67} 68 69/** 70 * read rl2 header data and setup the avstreams 71 * @param s demuxer context 72 * @param ap format parameters 73 * @return 0 on success, AVERROR otherwise 74 */ 75static av_cold int rl2_read_header(AVFormatContext *s, 76 AVFormatParameters *ap) 77{ 78 AVIOContext *pb = s->pb; 79 AVStream *st; 80 unsigned int frame_count; 81 unsigned int audio_frame_counter = 0; 82 unsigned int video_frame_counter = 0; 83 unsigned int back_size; 84 unsigned short sound_rate; 85 unsigned short rate; 86 unsigned short channels; 87 unsigned short def_sound_size; 88 unsigned int signature; 89 unsigned int pts_den = 11025; /* video only case */ 90 unsigned int pts_num = 1103; 91 unsigned int* chunk_offset = NULL; 92 int* chunk_size = NULL; 93 int* audio_size = NULL; 94 int i; 95 int ret = 0; 96 97 avio_skip(pb,4); /* skip FORM tag */ 98 back_size = avio_rl32(pb); /**< get size of the background frame */ 99 signature = avio_rb32(pb); 100 avio_skip(pb, 4); /* data size */ 101 frame_count = avio_rl32(pb); 102 103 /* disallow back_sizes and frame_counts that may lead to overflows later */ 104 if(back_size > INT_MAX/2 || frame_count > INT_MAX / sizeof(uint32_t)) 105 return AVERROR_INVALIDDATA; 106 107 avio_skip(pb, 2); /* encoding mentod */ 108 sound_rate = avio_rl16(pb); 109 rate = avio_rl16(pb); 110 channels = avio_rl16(pb); 111 def_sound_size = avio_rl16(pb); 112 113 /** setup video stream */ 114 st = avformat_new_stream(s, NULL); 115 if(!st) 116 return AVERROR(ENOMEM); 117 118 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 119 st->codec->codec_id = CODEC_ID_RL2; 120 st->codec->codec_tag = 0; /* no fourcc */ 121 st->codec->width = 320; 122 st->codec->height = 200; 123 124 /** allocate and fill extradata */ 125 st->codec->extradata_size = EXTRADATA1_SIZE; 126 127 if(signature == RLV3_TAG && back_size > 0) 128 st->codec->extradata_size += back_size; 129 130 st->codec->extradata = av_mallocz(st->codec->extradata_size + 131 FF_INPUT_BUFFER_PADDING_SIZE); 132 if(!st->codec->extradata) 133 return AVERROR(ENOMEM); 134 135 if(avio_read(pb,st->codec->extradata,st->codec->extradata_size) != 136 st->codec->extradata_size) 137 return AVERROR(EIO); 138 139 /** setup audio stream if present */ 140 if(sound_rate){ 141 pts_num = def_sound_size; 142 pts_den = rate; 143 144 st = avformat_new_stream(s, NULL); 145 if (!st) 146 return AVERROR(ENOMEM); 147 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 148 st->codec->codec_id = CODEC_ID_PCM_U8; 149 st->codec->codec_tag = 1; 150 st->codec->channels = channels; 151 st->codec->bits_per_coded_sample = 8; 152 st->codec->sample_rate = rate; 153 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 154 st->codec->bits_per_coded_sample; 155 st->codec->block_align = st->codec->channels * 156 st->codec->bits_per_coded_sample / 8; 157 avpriv_set_pts_info(st,32,1,rate); 158 } 159 160 avpriv_set_pts_info(s->streams[0], 32, pts_num, pts_den); 161 162 chunk_size = av_malloc(frame_count * sizeof(uint32_t)); 163 audio_size = av_malloc(frame_count * sizeof(uint32_t)); 164 chunk_offset = av_malloc(frame_count * sizeof(uint32_t)); 165 166 if(!chunk_size || !audio_size || !chunk_offset){ 167 av_free(chunk_size); 168 av_free(audio_size); 169 av_free(chunk_offset); 170 return AVERROR(ENOMEM); 171 } 172 173 /** read offset and size tables */ 174 for(i=0; i < frame_count;i++) 175 chunk_size[i] = avio_rl32(pb); 176 for(i=0; i < frame_count;i++) 177 chunk_offset[i] = avio_rl32(pb); 178 for(i=0; i < frame_count;i++) 179 audio_size[i] = avio_rl32(pb) & 0xFFFF; 180 181 /** build the sample index */ 182 for(i=0;i<frame_count;i++){ 183 if(chunk_size[i] < 0 || audio_size[i] > chunk_size[i]){ 184 ret = AVERROR_INVALIDDATA; 185 break; 186 } 187 188 if(sound_rate && audio_size[i]){ 189 av_add_index_entry(s->streams[1], chunk_offset[i], 190 audio_frame_counter,audio_size[i], 0, AVINDEX_KEYFRAME); 191 audio_frame_counter += audio_size[i] / channels; 192 } 193 av_add_index_entry(s->streams[0], chunk_offset[i] + audio_size[i], 194 video_frame_counter,chunk_size[i]-audio_size[i],0,AVINDEX_KEYFRAME); 195 ++video_frame_counter; 196 } 197 198 199 av_free(chunk_size); 200 av_free(audio_size); 201 av_free(chunk_offset); 202 203 return ret; 204} 205 206/** 207 * read a single audio or video packet 208 * @param s demuxer context 209 * @param pkt the packet to be filled 210 * @return 0 on success, AVERROR otherwise 211 */ 212static int rl2_read_packet(AVFormatContext *s, 213 AVPacket *pkt) 214{ 215 Rl2DemuxContext *rl2 = s->priv_data; 216 AVIOContext *pb = s->pb; 217 AVIndexEntry *sample = NULL; 218 int i; 219 int ret = 0; 220 int stream_id = -1; 221 int64_t pos = INT64_MAX; 222 223 /** check if there is a valid video or audio entry that can be used */ 224 for(i=0; i<s->nb_streams; i++){ 225 if(rl2->index_pos[i] < s->streams[i]->nb_index_entries 226 && s->streams[i]->index_entries[ rl2->index_pos[i] ].pos < pos){ 227 sample = &s->streams[i]->index_entries[ rl2->index_pos[i] ]; 228 pos= sample->pos; 229 stream_id= i; 230 } 231 } 232 233 if(stream_id == -1) 234 return AVERROR(EIO); 235 236 ++rl2->index_pos[stream_id]; 237 238 /** position the stream (will probably be there anyway) */ 239 avio_seek(pb, sample->pos, SEEK_SET); 240 241 /** fill the packet */ 242 ret = av_get_packet(pb, pkt, sample->size); 243 if(ret != sample->size){ 244 av_free_packet(pkt); 245 return AVERROR(EIO); 246 } 247 248 pkt->stream_index = stream_id; 249 pkt->pts = sample->timestamp; 250 251 return ret; 252} 253 254/** 255 * seek to a new timestamp 256 * @param s demuxer context 257 * @param stream_index index of the stream that should be seeked 258 * @param timestamp wanted timestamp 259 * @param flags direction and seeking mode 260 * @return 0 on success, -1 otherwise 261 */ 262static int rl2_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) 263{ 264 AVStream *st = s->streams[stream_index]; 265 Rl2DemuxContext *rl2 = s->priv_data; 266 int i; 267 int index = av_index_search_timestamp(st, timestamp, flags); 268 if(index < 0) 269 return -1; 270 271 rl2->index_pos[stream_index] = index; 272 timestamp = st->index_entries[index].timestamp; 273 274 for(i=0; i < s->nb_streams; i++){ 275 AVStream *st2 = s->streams[i]; 276 index = av_index_search_timestamp(st2, 277 av_rescale_q(timestamp, st->time_base, st2->time_base), 278 flags | AVSEEK_FLAG_BACKWARD); 279 280 if(index < 0) 281 index = 0; 282 283 rl2->index_pos[i] = index; 284 } 285 286 return 0; 287} 288 289AVInputFormat ff_rl2_demuxer = { 290 .name = "rl2", 291 .long_name = NULL_IF_CONFIG_SMALL("RL2 format"), 292 .priv_data_size = sizeof(Rl2DemuxContext), 293 .read_probe = rl2_probe, 294 .read_header = rl2_read_header, 295 .read_packet = rl2_read_packet, 296 .read_seek = rl2_read_seek, 297}; 298 299