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 <inttypes.h>
24
25
#include "
libavutil/intreadwrite.h
"
26
#include "
avformat.h
"
27
#include "
internal.h
"
28
29
#define HNM4_TAG MKTAG('H', 'N', 'M', '4')
30
31
#define HNM4_SAMPLE_RATE 22050
32
#define HNM4_FRAME_FPS 24
33
34
#define HNM4_CHUNK_ID_PL 19536
35
#define HNM4_CHUNK_ID_IZ 23113
36
#define HNM4_CHUNK_ID_IU 21833
37
#define HNM4_CHUNK_ID_SD 17491
38
39
typedef
struct
Hnm4DemuxContext
{
40
uint8_t
version
;
41
uint16_t
width
;
42
uint16_t
height
;
43
uint32_t
filesize
;
44
uint32_t
frames
;
45
uint32_t
taboffset
;
46
uint16_t
bits
;
47
uint16_t
channels
;
48
uint32_t
framesize
;
49
uint32_t
currentframe
;
50
int64_t
pts
;
51
uint32_t
superchunk_remaining
;
52
AVPacket
vpkt
;
53
}
Hnm4DemuxContext
;
54
55
static
int
hnm_probe
(
AVProbeData
*p)
56
{
57
if
(p->
buf_size
< 4)
58
return
0;
59
60
// check for HNM4 header.
61
// currently only HNM v4/v4A is supported
62
if
(
AV_RL32
(&p->
buf
[0]) ==
HNM4_TAG
)
63
return
AVPROBE_SCORE_MAX
;
64
65
return
0;
66
}
67
68
static
int
hnm_read_header
(
AVFormatContext
*
s
)
69
{
70
Hnm4DemuxContext
*hnm = s->
priv_data
;
71
AVIOContext
*pb = s->
pb
;
72
AVStream
*vst;
73
74
/* default context members */
75
hnm->
pts
= 0;
76
av_init_packet
(&hnm->
vpkt
);
77
hnm->
vpkt
.
data
= NULL;
78
hnm->
vpkt
.
size
= 0;
79
80
hnm->
superchunk_remaining
= 0;
81
82
avio_skip
(pb, 8);
83
hnm->
width
=
avio_rl16
(pb);
84
hnm->
height
=
avio_rl16
(pb);
85
hnm->
filesize
=
avio_rl32
(pb);
86
hnm->
frames
=
avio_rl32
(pb);
87
hnm->
taboffset
=
avio_rl32
(pb);
88
hnm->
bits
=
avio_rl16
(pb);
89
hnm->
channels
=
avio_rl16
(pb);
90
hnm->
framesize
=
avio_rl32
(pb);
91
avio_skip
(pb, 32);
92
93
hnm->
currentframe
= 0;
94
95
if
(hnm->
width
< 256 || hnm->
width
> 640 ||
96
hnm->
height
< 150 || hnm->
height
> 480) {
97
av_log
(s,
AV_LOG_ERROR
,
98
"invalid resolution: %ux%u\n"
, hnm->
width
, hnm->
height
);
99
return
AVERROR_INVALIDDATA
;
100
}
101
102
// TODO: find a better way to detect HNM4A
103
if
(hnm->
width
== 640)
104
hnm->
version
= 0x4a;
105
else
106
hnm->
version
= 0x40;
107
108
if
(!(vst =
avformat_new_stream
(s, NULL)))
109
return
AVERROR
(ENOMEM);
110
111
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
112
vst->
codec
->
codec_id
=
AV_CODEC_ID_HNM4_VIDEO
;
113
vst->
codec
->
codec_tag
= 0;
114
vst->
codec
->
width
= hnm->
width
;
115
vst->
codec
->
height
= hnm->
height
;
116
vst->
codec
->
extradata
=
av_mallocz
(1);
117
118
vst->
codec
->
extradata_size
= 1;
119
memcpy(vst->
codec
->
extradata
, &hnm->
version
, 1);
120
121
vst->
start_time
= 0;
122
123
avpriv_set_pts_info
(vst, 33, 1,
HNM4_FRAME_FPS
);
124
125
return
0;
126
}
127
128
static
int
hnm_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
129
{
130
Hnm4DemuxContext
*hnm = s->
priv_data
;
131
AVIOContext
*pb = s->
pb
;
132
int
ret
= 0;
133
134
uint32_t superchunk_size, chunk_size;
135
uint16_t chunk_id;
136
137
if
(hnm->
currentframe
== hnm->
frames
|| pb->
eof_reached
)
138
return
AVERROR_EOF
;
139
140
if
(hnm->
superchunk_remaining
== 0) {
141
/* parse next superchunk */
142
superchunk_size =
avio_rl24
(pb);
143
avio_skip
(pb, 1);
144
145
hnm->
superchunk_remaining
= superchunk_size - 4;
146
}
147
148
chunk_size =
avio_rl24
(pb);
149
avio_skip
(pb, 1);
150
chunk_id =
avio_rl16
(pb);
151
avio_skip
(pb, 2);
152
153
if
(chunk_size > hnm->
superchunk_remaining
|| !chunk_size) {
154
av_log
(s,
AV_LOG_ERROR
,
155
"invalid chunk size: %"
PRIu32
", offset: %"
PRId64
"\n"
,
156
chunk_size,
avio_tell
(pb));
157
avio_skip
(pb, hnm->
superchunk_remaining
- 8);
158
hnm->
superchunk_remaining
= 0;
159
}
160
161
switch
(chunk_id) {
162
case
HNM4_CHUNK_ID_PL
:
163
case
HNM4_CHUNK_ID_IZ
:
164
case
HNM4_CHUNK_ID_IU
:
165
avio_seek
(pb, -8, SEEK_CUR);
166
ret +=
av_get_packet
(pb, pkt, chunk_size);
167
hnm->
superchunk_remaining
-= chunk_size;
168
if
(chunk_id ==
HNM4_CHUNK_ID_IZ
|| chunk_id ==
HNM4_CHUNK_ID_IU
)
169
hnm->
currentframe
++;
170
break
;
171
172
case
HNM4_CHUNK_ID_SD
:
173
avio_skip
(pb, chunk_size - 8);
174
hnm->
superchunk_remaining
-= chunk_size;
175
break
;
176
177
default
:
178
av_log
(s,
AV_LOG_WARNING
,
"unknown chunk found: %"
PRIu16
", offset: %"
PRId64
"\n"
,
179
chunk_id,
avio_tell
(pb));
180
avio_skip
(pb, chunk_size - 8);
181
hnm->
superchunk_remaining
-= chunk_size;
182
break
;
183
}
184
185
return
ret
;
186
}
187
188
static
int
hnm_read_close
(
AVFormatContext
*
s
)
189
{
190
Hnm4DemuxContext
*hnm = s->
priv_data
;
191
192
if
(hnm->
vpkt
.
size
> 0)
193
av_free_packet
(&hnm->
vpkt
);
194
195
return
0;
196
}
197
198
AVInputFormat
ff_hnm_demuxer
= {
199
.
name
=
"hnm"
,
200
.long_name =
NULL_IF_CONFIG_SMALL
(
"Cryo HNM v4"
),
201
.priv_data_size =
sizeof
(
Hnm4DemuxContext
),
202
.
read_probe
=
hnm_probe
,
203
.
read_header
=
hnm_read_header
,
204
.
read_packet
=
hnm_read_packet
,
205
.
read_close
=
hnm_read_close
,
206
.
flags
=
AVFMT_NO_BYTE_SEEK
|
AVFMT_NOGENSEARCH
|
AVFMT_NOBINSEARCH
207
};
Generated on Fri Dec 5 2014 04:42:11 for FFmpeg by
1.8.2