FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
hnm.c
Go to the documentation of this file.
1
/*
2
* Cryo Interactive Entertainment HNM4 demuxer
3
*
4
* Copyright (c) 2012 David Kment
5
*
6
* This file is part of FFmpeg .
7
*
8
* FFmpeg is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* FFmpeg is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with FFmpeg ; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
#include "
libavutil/intreadwrite.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
27
#define HNM4_TAG MKTAG('H', 'N', 'M', '4')
28
29
#define HNM4_SAMPLE_RATE 22050
30
#define HNM4_FRAME_FPS 24
31
32
#define HNM4_CHUNK_ID_PL 19536
33
#define HNM4_CHUNK_ID_IZ 23113
34
#define HNM4_CHUNK_ID_IU 21833
35
#define HNM4_CHUNK_ID_SD 17491
36
37
typedef
struct
Hnm4DemuxContext
{
38
uint8_t
version
;
39
uint16_t
width
;
40
uint16_t
height
;
41
uint32_t
filesize
;
42
uint32_t
frames
;
43
uint32_t
taboffset
;
44
uint16_t
bits
;
45
uint16_t
channels
;
46
uint32_t
framesize
;
47
uint32_t
currentframe
;
48
int64_t
pts
;
49
uint32_t
superchunk_remaining
;
50
AVPacket
vpkt
;
51
}
Hnm4DemuxContext
;
52
53
static
int
hnm_probe
(
AVProbeData
*p)
54
{
55
if
(p->
buf_size
< 4)
56
return
0;
57
58
// check for HNM4 header.
59
// currently only HNM v4/v4A is supported
60
if
(
AV_RL32
(&p->
buf
[0]) ==
HNM4_TAG
)
61
return
AVPROBE_SCORE_MAX
;
62
63
return
0;
64
}
65
66
static
int
hnm_read_header
(
AVFormatContext
*
s
)
67
{
68
Hnm4DemuxContext
*hnm = s->
priv_data
;
69
AVIOContext
*pb = s->
pb
;
70
AVStream
*vst;
71
72
/* default context members */
73
hnm->
pts
= 0;
74
av_init_packet
(&hnm->
vpkt
);
75
hnm->
vpkt
.
data
= NULL;
76
hnm->
vpkt
.
size
= 0;
77
78
hnm->
superchunk_remaining
= 0;
79
80
avio_skip
(pb, 8);
81
hnm->
width
=
avio_rl16
(pb);
82
hnm->
height
=
avio_rl16
(pb);
83
hnm->
filesize
=
avio_rl32
(pb);
84
hnm->
frames
=
avio_rl32
(pb);
85
hnm->
taboffset
=
avio_rl32
(pb);
86
hnm->
bits
=
avio_rl16
(pb);
87
hnm->
channels
=
avio_rl16
(pb);
88
hnm->
framesize
=
avio_rl32
(pb);
89
avio_skip
(pb, 32);
90
91
hnm->
currentframe
= 0;
92
93
if
(hnm->
width
< 320 || hnm->
width
> 640 ||
94
hnm->
height
< 150 || hnm->
height
> 480) {
95
av_log
(s,
AV_LOG_ERROR
,
96
"invalid resolution: %ux%u\n"
, hnm->
width
, hnm->
height
);
97
return
AVERROR_INVALIDDATA
;
98
}
99
100
// TODO: find a better way to detect HNM4A
101
if
(hnm->
width
== 640)
102
hnm->
version
= 0x4a;
103
else
104
hnm->
version
= 0x40;
105
106
if
(!(vst =
avformat_new_stream
(s, NULL)))
107
return
AVERROR
(ENOMEM);
108
109
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
110
vst->
codec
->
codec_id
=
AV_CODEC_ID_HNM4_VIDEO
;
111
vst->
codec
->
codec_tag
= 0;
112
vst->
codec
->
width
= hnm->
width
;
113
vst->
codec
->
height
= hnm->
height
;
114
vst->
codec
->
extradata
=
av_mallocz
(1);
115
116
vst->
codec
->
extradata_size
= 1;
117
memcpy(vst->
codec
->
extradata
, &hnm->
version
, 1);
118
119
vst->
start_time
= 0;
120
121
avpriv_set_pts_info
(vst, 33, 1,
HNM4_FRAME_FPS
);
122
123
return
0;
124
}
125
126
static
int
hnm_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
127
{
128
Hnm4DemuxContext
*hnm = s->
priv_data
;
129
AVIOContext
*pb = s->
pb
;
130
int
ret
= 0;
131
132
uint32_t superchunk_size, chunk_size;
133
uint16_t chunk_id;
134
135
if
(hnm->
currentframe
== hnm->
frames
|| pb->
eof_reached
)
136
return
AVERROR_EOF
;
137
138
if
(hnm->
superchunk_remaining
== 0) {
139
/* parse next superchunk */
140
superchunk_size =
avio_rl24
(pb);
141
avio_skip
(pb, 1);
142
143
hnm->
superchunk_remaining
= superchunk_size - 4;
144
}
145
146
chunk_size =
avio_rl24
(pb);
147
avio_skip
(pb, 1);
148
chunk_id =
avio_rl16
(pb);
149
avio_skip
(pb, 2);
150
151
if
(chunk_size > hnm->
superchunk_remaining
|| !chunk_size) {
152
av_log
(s,
AV_LOG_ERROR
,
"invalid chunk size: %u, offset: %u\n"
,
153
chunk_size, (
int
)
avio_tell
(pb));
154
avio_skip
(pb, hnm->
superchunk_remaining
- 8);
155
hnm->
superchunk_remaining
= 0;
156
}
157
158
switch
(chunk_id) {
159
case
HNM4_CHUNK_ID_PL
:
160
case
HNM4_CHUNK_ID_IZ
:
161
case
HNM4_CHUNK_ID_IU
:
162
avio_seek
(pb, -8, SEEK_CUR);
163
ret +=
av_get_packet
(pb, pkt, chunk_size);
164
hnm->
superchunk_remaining
-= chunk_size;
165
if
(chunk_id ==
HNM4_CHUNK_ID_IZ
|| chunk_id ==
HNM4_CHUNK_ID_IU
)
166
hnm->
currentframe
++;
167
break
;
168
169
case
HNM4_CHUNK_ID_SD
:
170
avio_skip
(pb, chunk_size - 8);
171
hnm->
superchunk_remaining
-= chunk_size;
172
break
;
173
174
default
:
175
av_log
(s,
AV_LOG_WARNING
,
"unknown chunk found: %d, offset: %d\n"
,
176
chunk_id, (
int
)
avio_tell
(pb));
177
avio_skip
(pb, chunk_size - 8);
178
hnm->
superchunk_remaining
-= chunk_size;
179
break
;
180
}
181
182
return
ret
;
183
}
184
185
static
int
hnm_read_close
(
AVFormatContext
*
s
)
186
{
187
Hnm4DemuxContext
*hnm = s->
priv_data
;
188
189
if
(hnm->
vpkt
.
size
> 0)
190
av_free_packet
(&hnm->
vpkt
);
191
192
return
0;
193
}
194
195
AVInputFormat
ff_hnm_demuxer
= {
196
.
name
=
"hnm"
,
197
.long_name =
NULL_IF_CONFIG_SMALL
(
"Cryo HNM v4"
),
198
.priv_data_size =
sizeof
(
Hnm4DemuxContext
),
199
.
read_probe
=
hnm_probe
,
200
.
read_header
=
hnm_read_header
,
201
.
read_packet
=
hnm_read_packet
,
202
.
read_close
=
hnm_read_close
,
203
.
flags
=
AVFMT_NO_BYTE_SEEK
|
AVFMT_NOGENSEARCH
|
AVFMT_NOBINSEARCH
204
};
Generated on Sun Mar 23 2014 23:50:11 for FFmpeg by
1.8.2