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