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
25 * @author Sascha Sommer (saschasommer@freenet.de)
26 * @see http://wiki.multimedia.cx/index.php?title=RL2
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
37 #include "libavutil/intreadwrite.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/mem.h"
44 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr, palette
46 #define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
47 #define RLV2_TAG MKBETAG('R', 'L', 'V', '2')
48 #define RLV3_TAG MKBETAG('R', 'L', 'V', '3')
50 typedef struct Rl2DemuxContext
{
51 unsigned int index_pos
[2]; ///< indexes in the sample tables
56 * check if the file is in rl2 format
57 * @param p probe buffer
58 * @return 0 when the probe buffer does not contain rl2 data, > 0 otherwise
60 static int rl2_probe(const AVProbeData
*p
)
63 if(AV_RB32(&p
->buf
[0]) != FORM_TAG
)
66 if(AV_RB32(&p
->buf
[8]) != RLV2_TAG
&&
67 AV_RB32(&p
->buf
[8]) != RLV3_TAG
)
70 return AVPROBE_SCORE_MAX
;
74 * read rl2 header data and setup the avstreams
75 * @param s demuxer context
76 * @return 0 on success, AVERROR otherwise
78 static av_cold
int rl2_read_header(AVFormatContext
*s
)
80 AVIOContext
*pb
= s
->pb
;
82 unsigned int frame_count
;
83 unsigned int audio_frame_counter
= 0;
84 unsigned int video_frame_counter
= 0;
85 unsigned int back_size
;
86 unsigned short sound_rate
;
88 unsigned short channels
;
89 unsigned short def_sound_size
;
90 unsigned int signature
;
91 unsigned int pts_den
= 11025; /* video only case */
92 unsigned int pts_num
= 1103;
93 unsigned int* chunk_offset
= NULL
;
94 int* chunk_size
= NULL
;
95 int* audio_size
= NULL
;
99 avio_skip(pb
,4); /* skip FORM tag */
100 back_size
= avio_rl32(pb
); /**< get size of the background frame */
101 signature
= avio_rb32(pb
);
102 avio_skip(pb
, 4); /* data size */
103 frame_count
= avio_rl32(pb
);
105 /* disallow back_sizes and frame_counts that may lead to overflows later */
106 if(back_size
> INT_MAX
/2 || frame_count
> INT_MAX
/ sizeof(uint32_t))
107 return AVERROR_INVALIDDATA
;
109 avio_skip(pb
, 2); /* encoding method */
110 sound_rate
= avio_rl16(pb
);
111 rate
= avio_rl16(pb
);
112 channels
= avio_rl16(pb
);
113 def_sound_size
= avio_rl16(pb
);
115 /** setup video stream */
116 st
= avformat_new_stream(s
, NULL
);
118 return AVERROR(ENOMEM
);
120 st
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
121 st
->codecpar
->codec_id
= AV_CODEC_ID_RL2
;
122 st
->codecpar
->codec_tag
= 0; /* no fourcc */
123 st
->codecpar
->width
= 320;
124 st
->codecpar
->height
= 200;
126 /** allocate and fill extradata */
127 st
->codecpar
->extradata_size
= EXTRADATA1_SIZE
;
129 if(signature
== RLV3_TAG
&& back_size
> 0)
130 st
->codecpar
->extradata_size
+= back_size
;
132 ret
= ff_get_extradata(s
, st
->codecpar
, pb
, st
->codecpar
->extradata_size
);
136 /** setup audio stream if present */
138 if (!channels
|| channels
> 42) {
139 av_log(s
, AV_LOG_ERROR
, "Invalid number of channels: %d\n", channels
);
140 return AVERROR_INVALIDDATA
;
143 pts_num
= def_sound_size
;
146 st
= avformat_new_stream(s
, NULL
);
148 return AVERROR(ENOMEM
);
149 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
150 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_U8
;
151 st
->codecpar
->codec_tag
= 1;
152 st
->codecpar
->ch_layout
.nb_channels
= channels
;
153 st
->codecpar
->bits_per_coded_sample
= 8;
154 st
->codecpar
->sample_rate
= rate
;
155 st
->codecpar
->bit_rate
= channels
* st
->codecpar
->sample_rate
*
156 st
->codecpar
->bits_per_coded_sample
;
157 st
->codecpar
->block_align
= channels
*
158 st
->codecpar
->bits_per_coded_sample
/ 8;
159 avpriv_set_pts_info(st
,32,1,rate
);
162 avpriv_set_pts_info(s
->streams
[0], 32, pts_num
, pts_den
);
164 chunk_size
= av_malloc(frame_count
* sizeof(uint32_t));
165 audio_size
= av_malloc(frame_count
* sizeof(uint32_t));
166 chunk_offset
= av_malloc(frame_count
* sizeof(uint32_t));
168 if(!chunk_size
|| !audio_size
|| !chunk_offset
){
171 av_free(chunk_offset
);
172 return AVERROR(ENOMEM
);
175 /** read offset and size tables */
176 for(i
=0; i
< frame_count
;i
++) {
178 ret
= AVERROR_INVALIDDATA
;
181 chunk_size
[i
] = avio_rl32(pb
);
183 for(i
=0; i
< frame_count
;i
++) {
185 ret
= AVERROR_INVALIDDATA
;
188 chunk_offset
[i
] = avio_rl32(pb
);
190 for(i
=0; i
< frame_count
;i
++) {
192 ret
= AVERROR_INVALIDDATA
;
195 audio_size
[i
] = avio_rl32(pb
) & 0xFFFF;
198 /** build the sample index */
199 for(i
=0;i
<frame_count
;i
++){
200 if(chunk_size
[i
] < 0 || audio_size
[i
] > chunk_size
[i
]){
201 ret
= AVERROR_INVALIDDATA
;
205 if(sound_rate
&& audio_size
[i
]){
206 av_add_index_entry(s
->streams
[1], chunk_offset
[i
],
207 audio_frame_counter
,audio_size
[i
], 0, AVINDEX_KEYFRAME
);
208 audio_frame_counter
+= audio_size
[i
] / channels
;
210 av_add_index_entry(s
->streams
[0], chunk_offset
[i
] + audio_size
[i
],
211 video_frame_counter
,chunk_size
[i
]-audio_size
[i
],0,AVINDEX_KEYFRAME
);
212 ++video_frame_counter
;
218 av_free(chunk_offset
);
224 * read a single audio or video packet
225 * @param s demuxer context
226 * @param pkt the packet to be filled
227 * @return 0 on success, AVERROR otherwise
229 static int rl2_read_packet(AVFormatContext
*s
,
232 Rl2DemuxContext
*rl2
= s
->priv_data
;
233 AVIOContext
*pb
= s
->pb
;
234 AVIndexEntry
*sample
= NULL
;
238 int64_t pos
= INT64_MAX
;
240 /** check if there is a valid video or audio entry that can be used */
241 for(i
=0; i
<s
->nb_streams
; i
++){
242 const FFStream
*const sti
= ffstream(s
->streams
[i
]);
243 if (rl2
->index_pos
[i
] < sti
->nb_index_entries
244 && sti
->index_entries
[ rl2
->index_pos
[i
] ].pos
< pos
) {
245 sample
= &sti
->index_entries
[ rl2
->index_pos
[i
] ];
254 ++rl2
->index_pos
[stream_id
];
256 /** position the stream (will probably be there anyway) */
257 avio_seek(pb
, sample
->pos
, SEEK_SET
);
259 /** fill the packet */
260 ret
= av_get_packet(pb
, pkt
, sample
->size
);
261 if(ret
!= sample
->size
){
262 return AVERROR_INVALIDDATA
;
265 pkt
->stream_index
= stream_id
;
266 pkt
->pts
= sample
->timestamp
;
272 * seek to a new timestamp
273 * @param s demuxer context
274 * @param stream_index index of the stream that should be seeked
275 * @param timestamp wanted timestamp
276 * @param flags direction and seeking mode
277 * @return 0 on success, -1 otherwise
279 static int rl2_read_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
)
281 AVStream
*st
= s
->streams
[stream_index
];
282 Rl2DemuxContext
*rl2
= s
->priv_data
;
284 int index
= av_index_search_timestamp(st
, timestamp
, flags
);
288 rl2
->index_pos
[stream_index
] = index
;
289 timestamp
= ffstream(st
)->index_entries
[index
].timestamp
;
291 for(i
=0; i
< s
->nb_streams
; i
++){
292 AVStream
*st2
= s
->streams
[i
];
293 index
= av_index_search_timestamp(st2
,
294 av_rescale_q(timestamp
, st
->time_base
, st2
->time_base
),
295 flags
| AVSEEK_FLAG_BACKWARD
);
300 rl2
->index_pos
[i
] = index
;
306 const FFInputFormat ff_rl2_demuxer
= {
308 .p
.long_name
= NULL_IF_CONFIG_SMALL("RL2"),
309 .priv_data_size
= sizeof(Rl2DemuxContext
),
310 .read_probe
= rl2_probe
,
311 .read_header
= rl2_read_header
,
312 .read_packet
= rl2_read_packet
,
313 .read_seek
= rl2_read_seek
,