3 * Copyright (c) 2008 Sascha Sommer (saschasommer@freenet.de)
5 * This file is part of FFmpeg.
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.
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.
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
24 * @file libavformat/rl2.c
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
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
36 #include "libavutil/intreadwrite.h"
39 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr, palette
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')
45 typedef struct Rl2DemuxContext
{
46 unsigned int index_pos
[2]; ///< indexes in the sample tables
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
55 static int rl2_probe(AVProbeData
*p
)
58 if(AV_RB32(&p
->buf
[0]) != FORM_TAG
)
61 if(AV_RB32(&p
->buf
[8]) != RLV2_TAG
&&
62 AV_RB32(&p
->buf
[8]) != RLV3_TAG
)
65 return AVPROBE_SCORE_MAX
;
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
74 static av_cold
int rl2_read_header(AVFormatContext
*s
,
75 AVFormatParameters
*ap
)
77 ByteIOContext
*pb
= s
->pb
;
79 unsigned int frame_count
;
80 unsigned int audio_frame_counter
= 0;
81 unsigned int video_frame_counter
= 0;
82 unsigned int back_size
;
84 unsigned short encoding_method
;
85 unsigned short sound_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
;
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
);
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
;
108 encoding_method
= get_le16(pb
);
109 sound_rate
= get_le16(pb
);
111 channels
= get_le16(pb
);
112 def_sound_size
= get_le16(pb
);
114 /** setup video stream */
115 st
= av_new_stream(s
, 0);
117 return AVERROR(ENOMEM
);
119 st
->codec
->codec_type
= CODEC_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;
125 /** allocate and fill extradata */
126 st
->codec
->extradata_size
= EXTRADATA1_SIZE
;
128 if(signature
== RLV3_TAG
&& back_size
> 0)
129 st
->codec
->extradata_size
+= back_size
;
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
);
136 if(get_buffer(pb
,st
->codec
->extradata
,st
->codec
->extradata_size
) !=
137 st
->codec
->extradata_size
)
140 /** setup audio stream if present */
142 pts_num
= def_sound_size
;
145 st
= av_new_stream(s
, 0);
147 return AVERROR(ENOMEM
);
148 st
->codec
->codec_type
= CODEC_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
);
161 av_set_pts_info(s
->streams
[0], 32, pts_num
, pts_den
);
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));
167 if(!chunk_size
|| !audio_size
|| !chunk_offset
){
170 av_free(chunk_offset
);
171 return AVERROR(ENOMEM
);
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;
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
;
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
;
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
;
202 av_free(chunk_offset
);
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
213 static int rl2_read_packet(AVFormatContext
*s
,
216 Rl2DemuxContext
*rl2
= s
->priv_data
;
217 ByteIOContext
*pb
= s
->pb
;
218 AVIndexEntry
*sample
= NULL
;
222 int64_t pos
= INT64_MAX
;
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
] ];
237 ++rl2
->index_pos
[stream_id
];
239 /** position the stream (will probably be there anyway) */
240 url_fseek(pb
, sample
->pos
, SEEK_SET
);
242 /** fill the packet */
243 ret
= av_get_packet(pb
, pkt
, sample
->size
);
244 if(ret
!= sample
->size
){
249 pkt
->stream_index
= stream_id
;
250 pkt
->pts
= sample
->timestamp
;
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
263 static int rl2_read_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
)
265 AVStream
*st
= s
->streams
[stream_index
];
266 Rl2DemuxContext
*rl2
= s
->priv_data
;
268 int index
= av_index_search_timestamp(st
, timestamp
, flags
);
272 rl2
->index_pos
[stream_index
] = index
;
273 timestamp
= st
->index_entries
[index
].timestamp
;
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
);
284 rl2
->index_pos
[i
] = index
;
290 AVInputFormat rl2_demuxer
= {
292 NULL_IF_CONFIG_SMALL("RL2 format"),
293 sizeof(Rl2DemuxContext
),