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 Sun Sep 14 2014 18:56:12 for FFmpeg by
1.8.2