FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
c93.c
Go to the documentation of this file.
1
/*
2
* Interplay C93 demuxer
3
* Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
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
#include "
avformat.h
"
23
#include "
internal.h
"
24
#include "
voc.h
"
25
#include "
libavutil/intreadwrite.h
"
26
27
typedef
struct
{
28
uint16_t
index
;
29
uint8_t
length
;
30
uint8_t
frames
;
31
}
C93BlockRecord
;
32
33
typedef
struct
{
34
VocDecContext
voc
;
35
36
C93BlockRecord
block_records[512];
37
int
current_block
;
38
39
uint32_t frame_offsets[32];
40
int
current_frame
;
41
int
next_pkt_is_audio
;
42
43
AVStream
*
audio
;
44
}
C93DemuxContext
;
45
46
static
int
probe
(
AVProbeData
*p)
47
{
48
int
i;
49
int
index
= 1;
50
if
(p->
buf_size
< 16)
51
return
0;
52
for
(i = 0; i < 16; i += 4) {
53
if
(
AV_RL16
(p->
buf
+ i) != index || !p->
buf
[i + 2] || !p->
buf
[i + 3])
54
return
0;
55
index += p->
buf
[i + 2];
56
}
57
return
AVPROBE_SCORE_MAX
;
58
}
59
60
static
int
read_header
(
AVFormatContext
*s)
61
{
62
AVStream
*video;
63
AVIOContext
*pb = s->
pb
;
64
C93DemuxContext
*c93 = s->
priv_data
;
65
int
i;
66
int
framecount = 0;
67
68
for
(i = 0; i < 512; i++) {
69
c93->
block_records
[i].
index
=
avio_rl16
(pb);
70
c93->
block_records
[i].
length
=
avio_r8
(pb);
71
c93->
block_records
[i].
frames
=
avio_r8
(pb);
72
if
(c93->
block_records
[i].
frames
> 32) {
73
av_log
(s,
AV_LOG_ERROR
,
"too many frames in block\n"
);
74
return
AVERROR_INVALIDDATA
;
75
}
76
framecount += c93->
block_records
[i].
frames
;
77
}
78
79
/* Audio streams are added if audio packets are found */
80
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
81
82
video =
avformat_new_stream
(s,
NULL
);
83
if
(!video)
84
return
AVERROR
(ENOMEM);
85
86
video->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
87
video->
codec
->
codec_id
=
AV_CODEC_ID_C93
;
88
video->
codec
->
width
= 320;
89
video->
codec
->
height
= 192;
90
/* 4:3 320x200 with 8 empty lines */
91
video->
sample_aspect_ratio
= (
AVRational
) { 5, 6 };
92
avpriv_set_pts_info
(video, 64, 2, 25);
93
video->
nb_frames
= framecount;
94
video->
duration
= framecount;
95
video->
start_time
= 0;
96
97
c93->
current_block
= 0;
98
c93->
current_frame
= 0;
99
c93->
next_pkt_is_audio
= 0;
100
return
0;
101
}
102
103
#define C93_HAS_PALETTE 0x01
104
#define C93_FIRST_FRAME 0x02
105
106
static
int
read_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
107
{
108
AVIOContext
*pb = s->
pb
;
109
C93DemuxContext
*c93 = s->
priv_data
;
110
C93BlockRecord
*br = &c93->
block_records
[c93->
current_block
];
111
int
datasize;
112
int
ret, i;
113
114
if
(c93->
next_pkt_is_audio
) {
115
c93->
current_frame
++;
116
c93->
next_pkt_is_audio
= 0;
117
datasize =
avio_rl16
(pb);
118
if
(datasize > 42) {
119
if
(!c93->
audio
) {
120
c93->
audio
=
avformat_new_stream
(s,
NULL
);
121
if
(!c93->
audio
)
122
return
AVERROR
(ENOMEM);
123
c93->
audio
->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
124
}
125
avio_skip
(pb, 26);
/* VOC header */
126
ret =
ff_voc_get_packet
(s, pkt, c93->
audio
, datasize - 26);
127
if
(ret > 0) {
128
pkt->
stream_index
= 1;
129
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
130
return
ret;
131
}
132
}
133
}
134
if
(c93->
current_frame
>= br->
frames
) {
135
if
(c93->
current_block
>= 511 || !br[1].
length
)
136
return
AVERROR_EOF
;
137
br++;
138
c93->
current_block
++;
139
c93->
current_frame
= 0;
140
}
141
142
if
(c93->
current_frame
== 0) {
143
avio_seek
(pb, br->
index
* 2048, SEEK_SET);
144
for
(i = 0; i < 32; i++) {
145
c93->
frame_offsets
[i] =
avio_rl32
(pb);
146
}
147
}
148
149
avio_seek
(pb,br->
index
* 2048 +
150
c93->
frame_offsets
[c93->
current_frame
], SEEK_SET);
151
datasize =
avio_rl16
(pb);
/* video frame size */
152
153
ret =
av_new_packet
(pkt, datasize + 768 + 1);
154
if
(ret < 0)
155
return
ret;
156
pkt->
data
[0] = 0;
157
pkt->
size
= datasize + 1;
158
159
ret =
avio_read
(pb, pkt->
data
+ 1, datasize);
160
if
(ret < datasize) {
161
ret =
AVERROR
(EIO);
162
goto
fail;
163
}
164
165
datasize =
avio_rl16
(pb);
/* palette size */
166
if
(datasize) {
167
if
(datasize != 768) {
168
av_log
(s,
AV_LOG_ERROR
,
"invalid palette size %u\n"
, datasize);
169
ret =
AVERROR_INVALIDDATA
;
170
goto
fail;
171
}
172
pkt->
data
[0] |=
C93_HAS_PALETTE
;
173
ret =
avio_read
(pb, pkt->
data
+ pkt->
size
, datasize);
174
if
(ret < datasize) {
175
ret =
AVERROR
(EIO);
176
goto
fail;
177
}
178
pkt->
size
+= 768;
179
}
180
pkt->
stream_index
= 0;
181
c93->
next_pkt_is_audio
= 1;
182
183
/* only the first frame is guaranteed to not reference previous frames */
184
if
(c93->
current_block
== 0 && c93->
current_frame
== 0) {
185
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
186
pkt->
data
[0] |=
C93_FIRST_FRAME
;
187
}
188
return
0;
189
190
fail:
191
av_free_packet
(pkt);
192
return
ret;
193
}
194
195
AVInputFormat
ff_c93_demuxer
= {
196
.
name
=
"c93"
,
197
.long_name =
NULL_IF_CONFIG_SMALL
(
"Interplay C93"
),
198
.priv_data_size =
sizeof
(
C93DemuxContext
),
199
.
read_probe
=
probe
,
200
.
read_header
=
read_header
,
201
.
read_packet
=
read_packet
,
202
};
Generated on Sat May 25 2013 04:01:02 for FFmpeg by
1.8.2