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