2 * Bitmap Brothers JV demuxer
3 * Copyright (c) 2005, 2011 Peter Ross <pross@xvid.org>
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 * Bitmap Brothers JV demuxer
25 * @author Peter Ross <pross@xvid.org>
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/mem.h"
36 #define JV_PREAMBLE_SIZE 5
38 typedef struct JVFrame
{
39 int audio_size
; /**< audio packet size (bytes) */
40 int video_size
; /**< video packet size (bytes) */
41 uint16_t palette_size
; /**< palette size (bytes) */
42 uint8_t video_type
; /**< per-frame video compression type */
45 typedef struct JVDemuxContext
{
55 #define MAGIC " Compression by John M Phillips Copyright (C) 1995 The Bitmap Brothers Ltd."
57 static int read_probe(const AVProbeData
*pd
)
59 if (pd
->buf
[0] == 'J' && pd
->buf
[1] == 'V' && strlen(MAGIC
) + 4 <= pd
->buf_size
&&
60 !memcmp(pd
->buf
+ 4, MAGIC
, strlen(MAGIC
)))
61 return AVPROBE_SCORE_MAX
;
65 static int read_close(AVFormatContext
*s
)
67 JVDemuxContext
*jv
= s
->priv_data
;
69 av_freep(&jv
->frames
);
74 static int read_header(AVFormatContext
*s
)
76 JVDemuxContext
*jv
= s
->priv_data
;
77 AVIOContext
*pb
= s
->pb
;
80 int64_t audio_pts
= 0;
85 ast
= avformat_new_stream(s
, NULL
);
86 vst
= avformat_new_stream(s
, NULL
);
88 return AVERROR(ENOMEM
);
91 vst
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
92 vst
->codecpar
->codec_id
= AV_CODEC_ID_JV
;
93 vst
->codecpar
->codec_tag
= 0; /* no fourcc */
94 vst
->codecpar
->width
= avio_rl16(pb
);
95 vst
->codecpar
->height
= avio_rl16(pb
);
98 asti
->nb_index_entries
= avio_rl16(pb
);
99 avpriv_set_pts_info(vst
, 64, avio_rl16(pb
), 1000);
103 ast
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
104 ast
->codecpar
->codec_id
= AV_CODEC_ID_PCM_U8
;
105 ast
->codecpar
->codec_tag
= 0; /* no fourcc */
106 ast
->codecpar
->sample_rate
= avio_rl16(pb
);
107 ast
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
108 avpriv_set_pts_info(ast
, 64, 1, ast
->codecpar
->sample_rate
);
112 asti
->index_entries
= av_malloc(asti
->nb_index_entries
*
113 sizeof(*asti
->index_entries
));
114 if (!asti
->index_entries
)
115 return AVERROR(ENOMEM
);
117 jv
->frames
= av_malloc(asti
->nb_index_entries
* sizeof(*jv
->frames
));
119 return AVERROR(ENOMEM
);
120 offset
= 0x68 + asti
->nb_index_entries
* 16;
121 for (int i
= 0; i
< asti
->nb_index_entries
; i
++) {
122 AVIndexEntry
*e
= asti
->index_entries
+ i
;
123 JVFrame
*jvf
= jv
->frames
+ i
;
125 /* total frame size including audio, video, palette data and padding */
126 e
->size
= avio_rl32(pb
);
131 jvf
->audio_size
= avio_rl32(pb
);
132 jvf
->video_size
= avio_rl32(pb
);
133 jvf
->palette_size
= avio_r8(pb
) ? 768 : 0;
135 if ((jvf
->video_size
| jvf
->audio_size
) & ~0xFFFFFF ||
136 e
->size
- jvf
->audio_size
138 - jvf
->palette_size
< 0) {
139 if (s
->error_recognition
& AV_EF_EXPLODE
)
140 return AVERROR_INVALIDDATA
;
143 jvf
->palette_size
= 0;
147 av_log(s
, AV_LOG_WARNING
, "unsupported audio codec\n");
149 jvf
->video_type
= avio_r8(pb
);
152 e
->timestamp
= jvf
->audio_size
? audio_pts
: AV_NOPTS_VALUE
;
153 audio_pts
+= jvf
->audio_size
;
155 e
->flags
= jvf
->video_type
!= 1 ? AVINDEX_KEYFRAME
: 0;
158 jv
->state
= JV_AUDIO
;
162 static int read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
164 JVDemuxContext
*jv
= s
->priv_data
;
165 AVIOContext
*pb
= s
->pb
;
166 AVStream
*ast
= s
->streams
[0];
167 FFStream
*const asti
= ffstream(ast
);
170 while (!avio_feof(s
->pb
) && jv
->pts
< asti
->nb_index_entries
) {
171 const AVIndexEntry
*const e
= asti
->index_entries
+ jv
->pts
;
172 const JVFrame
*jvf
= jv
->frames
+ jv
->pts
;
177 if (jvf
->audio_size
) {
178 if ((ret
= av_get_packet(s
->pb
, pkt
, jvf
->audio_size
)) < 0)
180 pkt
->stream_index
= 0;
181 pkt
->pts
= e
->timestamp
;
182 pkt
->flags
|= AV_PKT_FLAG_KEY
;
187 if (jvf
->video_size
|| jvf
->palette_size
) {
188 int size
= jvf
->video_size
+ jvf
->palette_size
;
189 if ((ret
= av_new_packet(pkt
, size
+ JV_PREAMBLE_SIZE
)) < 0)
192 AV_WL32(pkt
->data
, jvf
->video_size
);
193 pkt
->data
[4] = jvf
->video_type
;
194 ret
= avio_read(pb
, pkt
->data
+ JV_PREAMBLE_SIZE
, size
);
198 memset(pkt
->data
+ JV_PREAMBLE_SIZE
+ ret
, 0,
199 AV_INPUT_BUFFER_PADDING_SIZE
);
200 pkt
->flags
|= AV_PKT_FLAG_CORRUPT
;
202 pkt
->size
= ret
+ JV_PREAMBLE_SIZE
;
203 pkt
->stream_index
= 1;
205 if (jvf
->video_type
!= 1)
206 pkt
->flags
|= AV_PKT_FLAG_KEY
;
210 avio_skip(pb
, FFMAX(e
->size
- jvf
->audio_size
- jvf
->video_size
211 - jvf
->palette_size
, 0));
212 jv
->state
= JV_AUDIO
;
217 if (s
->pb
->eof_reached
)
220 return AVERROR_INVALIDDATA
;
223 static int read_seek(AVFormatContext
*s
, int stream_index
,
224 int64_t ts
, int flags
)
226 JVDemuxContext
*jv
= s
->priv_data
;
227 AVStream
*ast
= s
->streams
[0];
228 FFStream
*const asti
= ffstream(ast
);
231 if (flags
& (AVSEEK_FLAG_BYTE
| AVSEEK_FLAG_FRAME
))
232 return AVERROR(ENOSYS
);
234 switch (stream_index
) {
236 i
= av_index_search_timestamp(ast
, ts
, flags
);
245 if (i
< 0 || i
>= asti
->nb_index_entries
)
247 if (avio_seek(s
->pb
, asti
->index_entries
[i
].pos
, SEEK_SET
) < 0)
250 jv
->state
= JV_AUDIO
;
255 const FFInputFormat ff_jv_demuxer
= {
257 .p
.long_name
= NULL_IF_CONFIG_SMALL("Bitmap Brothers JV"),
258 .priv_data_size
= sizeof(JVDemuxContext
),
259 .flags_internal
= FF_INFMT_FLAG_INIT_CLEANUP
,
260 .read_probe
= read_probe
,
261 .read_header
= read_header
,
262 .read_packet
= read_packet
,
263 .read_seek
= read_seek
,
264 .read_close
= read_close
,