Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
mvi.c
Go to the documentation of this file.
1
/*
2
* Motion Pixels MVI Demuxer
3
* Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net)
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; 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
25
#define MVI_FRAC_BITS 10
26
27
#define MVI_AUDIO_STREAM_INDEX 0
28
#define MVI_VIDEO_STREAM_INDEX 1
29
30
typedef
struct
MviDemuxContext
{
31
unsigned
int (*
get_int
)(
AVIOContext
*);
32
uint32_t
audio_data_size
;
33
uint64_t
audio_size_counter
;
34
uint64_t
audio_frame_size
;
35
int
audio_size_left
;
36
int
video_frame_size
;
37
}
MviDemuxContext
;
38
39
static
int
read_header
(
AVFormatContext
*s,
AVFormatParameters
*ap)
40
{
41
MviDemuxContext
*mvi = s->
priv_data
;
42
AVIOContext
*pb = s->
pb
;
43
AVStream
*ast, *vst;
44
unsigned
int
version
, frames_count, msecs_per_frame, player_version;
45
46
ast =
avformat_new_stream
(s,
NULL
);
47
if
(!ast)
48
return
AVERROR
(ENOMEM);
49
50
vst =
avformat_new_stream
(s,
NULL
);
51
if
(!vst)
52
return
AVERROR
(ENOMEM);
53
54
vst->
codec
->
extradata_size
= 2;
55
vst->
codec
->
extradata
=
av_mallocz
(2 +
FF_INPUT_BUFFER_PADDING_SIZE
);
56
57
version =
avio_r8
(pb);
58
vst->
codec
->
extradata
[0] =
avio_r8
(pb);
59
vst->
codec
->
extradata
[1] =
avio_r8
(pb);
60
frames_count =
avio_rl32
(pb);
61
msecs_per_frame =
avio_rl32
(pb);
62
vst->
codec
->
width
=
avio_rl16
(pb);
63
vst->
codec
->
height
=
avio_rl16
(pb);
64
avio_r8
(pb);
65
ast->
codec
->
sample_rate
=
avio_rl16
(pb);
66
mvi->
audio_data_size
=
avio_rl32
(pb);
67
avio_r8
(pb);
68
player_version =
avio_rl32
(pb);
69
avio_rl16
(pb);
70
avio_r8
(pb);
71
72
if
(frames_count == 0 || mvi->
audio_data_size
== 0)
73
return
AVERROR_INVALIDDATA
;
74
75
if
(version != 7 || player_version > 213) {
76
av_log
(s,
AV_LOG_ERROR
,
"unhandled version (%d,%d)\n"
, version, player_version);
77
return
AVERROR_INVALIDDATA
;
78
}
79
80
avpriv_set_pts_info
(ast, 64, 1, ast->
codec
->
sample_rate
);
81
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
82
ast->
codec
->
codec_id
=
CODEC_ID_PCM_U8
;
83
ast->
codec
->
channels
= 1;
84
ast->
codec
->
bits_per_coded_sample
= 8;
85
ast->
codec
->
bit_rate
= ast->
codec
->
sample_rate
* 8;
86
87
avpriv_set_pts_info
(vst, 64, msecs_per_frame, 1000000);
88
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
89
vst->
codec
->
codec_id
=
CODEC_ID_MOTIONPIXELS
;
90
91
mvi->
get_int
= (vst->
codec
->
width
* vst->
codec
->
height
< (1 << 16)) ?
avio_rl16
:
avio_rl24
;
92
93
mvi->
audio_frame_size
= ((uint64_t)mvi->
audio_data_size
<<
MVI_FRAC_BITS
) / frames_count;
94
if
(mvi->
audio_frame_size
<= 1 <<
MVI_FRAC_BITS
- 1) {
95
av_log
(s,
AV_LOG_ERROR
,
"Invalid audio_data_size (%d) or frames_count (%d)\n"
,
96
mvi->
audio_data_size
, frames_count);
97
return
AVERROR_INVALIDDATA
;
98
}
99
100
mvi->
audio_size_counter
= (ast->
codec
->
sample_rate
* 830 / mvi->
audio_frame_size
- 1) * mvi->
audio_frame_size
;
101
mvi->
audio_size_left
= mvi->
audio_data_size
;
102
103
return
0;
104
}
105
106
static
int
read_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
107
{
108
int
ret, count;
109
MviDemuxContext
*mvi = s->
priv_data
;
110
AVIOContext
*pb = s->
pb
;
111
112
if
(mvi->
video_frame_size
== 0) {
113
mvi->
video_frame_size
= (mvi->
get_int
)(pb);
114
if
(mvi->
audio_size_left
== 0)
115
return
AVERROR
(EIO);
116
count = (mvi->
audio_size_counter
+ mvi->
audio_frame_size
+ 512) >>
MVI_FRAC_BITS
;
117
if
(count > mvi->
audio_size_left
)
118
count = mvi->
audio_size_left
;
119
if
((ret =
av_get_packet
(pb, pkt, count)) < 0)
120
return
ret;
121
pkt->
stream_index
=
MVI_AUDIO_STREAM_INDEX
;
122
mvi->
audio_size_left
-= count;
123
mvi->
audio_size_counter
+= mvi->
audio_frame_size
- (count <<
MVI_FRAC_BITS
);
124
}
else
{
125
if
((ret =
av_get_packet
(pb, pkt, mvi->
video_frame_size
)) < 0)
126
return
ret;
127
pkt->
stream_index
=
MVI_VIDEO_STREAM_INDEX
;
128
mvi->
video_frame_size
= 0;
129
}
130
return
0;
131
}
132
133
AVInputFormat
ff_mvi_demuxer
= {
134
.
name
=
"mvi"
,
135
.long_name =
NULL_IF_CONFIG_SMALL
(
"Motion Pixels MVI format"
),
136
.priv_data_size =
sizeof
(
MviDemuxContext
),
137
.
read_header
=
read_header
,
138
.
read_packet
=
read_packet
,
139
.extensions =
"mvi"
140
};