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