Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
bmv.c
Go to the documentation of this file.
1
/*
2
* Discworld II BMV demuxer
3
* Copyright (c) 2011 Konstantin Shishkov.
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
enum
BMVFlags
{
26
BMV_NOP
= 0,
27
BMV_END
,
28
BMV_DELTA
,
29
BMV_INTRA
,
30
31
BMV_AUDIO
= 0x20,
32
};
33
34
typedef
struct
BMVContext
{
35
uint8_t *
packet
;
36
int
size
;
37
int
get_next
;
38
int64_t
audio_pos
;
39
}
BMVContext
;
40
41
static
int
bmv_read_header
(
AVFormatContext
*s,
AVFormatParameters
*ap)
42
{
43
AVStream
*st, *ast;
44
BMVContext
*c = s->
priv_data
;
45
46
st =
avformat_new_stream
(s, 0);
47
if
(!st)
48
return
AVERROR
(ENOMEM);
49
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
50
st->
codec
->
codec_id
=
CODEC_ID_BMV_VIDEO
;
51
st->
codec
->
width
= 640;
52
st->
codec
->
height
= 429;
53
st->
codec
->
pix_fmt
=
PIX_FMT_PAL8
;
54
avpriv_set_pts_info
(st, 16, 1, 12);
55
ast =
avformat_new_stream
(s, 0);
56
if
(!ast)
57
return
AVERROR
(ENOMEM);
58
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
59
ast->
codec
->
codec_id
=
CODEC_ID_BMV_AUDIO
;
60
ast->
codec
->
channels
= 2;
61
ast->
codec
->
sample_rate
= 22050;
62
avpriv_set_pts_info
(ast, 16, 1, 22050);
63
64
c->
get_next
= 1;
65
c->
audio_pos
= 0;
66
return
0;
67
}
68
69
static
int
bmv_read_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
70
{
71
BMVContext
*c = s->
priv_data
;
72
int
type;
73
void
*tmp;
74
75
while
(c->
get_next
) {
76
if
(s->
pb
->
eof_reached
)
77
return
AVERROR_EOF
;
78
type =
avio_r8
(s->
pb
);
79
if
(type ==
BMV_NOP
)
80
continue
;
81
if
(type ==
BMV_END
)
82
return
AVERROR_EOF
;
83
c->
size
=
avio_rl24
(s->
pb
);
84
if
(!c->
size
)
85
return
AVERROR_INVALIDDATA
;
86
tmp =
av_realloc
(c->
packet
, c->
size
+ 1);
87
if
(!tmp)
88
return
AVERROR
(ENOMEM);
89
c->
packet
= tmp;
90
c->
packet
[0] = type;
91
if
(
avio_read
(s->
pb
, c->
packet
+ 1, c->
size
) != c->
size
)
92
return
AVERROR
(EIO);
93
if
(type &
BMV_AUDIO
) {
94
int
audio_size
= c->
packet
[1] * 65 + 1;
95
if
(audio_size >= c->
size
) {
96
av_log
(s,
AV_LOG_ERROR
,
"Reported audio size %d is bigger than packet size (%d)\n"
,
97
audio_size, c->
size
);
98
return
AVERROR_INVALIDDATA
;
99
}
100
if
(
av_new_packet
(pkt, audio_size) < 0)
101
return
AVERROR
(ENOMEM);
102
memcpy(pkt->
data
, c->
packet
+ 1, pkt->
size
);
103
pkt->
stream_index
= 1;
104
pkt->
pts
= c->
audio_pos
;
105
pkt->
duration
= c->
packet
[1] * 32;
106
c->
audio_pos
+= pkt->
duration
;
107
c->
get_next
= 0;
108
return
pkt->
size
;
109
}
else
110
break
;
111
}
112
if
(
av_new_packet
(pkt, c->
size
+ 1) < 0)
113
return
AVERROR
(ENOMEM);
114
pkt->
stream_index
= 0;
115
c->
get_next
= 1;
116
memcpy(pkt->
data
, c->
packet
, pkt->
size
);
117
return
pkt->
size
;
118
}
119
120
static
int
bmv_read_close
(
AVFormatContext
*s)
121
{
122
BMVContext
*c = s->
priv_data
;
123
124
av_freep
(&c->
packet
);
125
126
return
0;
127
}
128
129
AVInputFormat
ff_bmv_demuxer
= {
130
.
name
=
"bmv"
,
131
.long_name =
NULL_IF_CONFIG_SMALL
(
"Discworld II BMV"
),
132
.priv_data_size =
sizeof
(
BMVContext
),
133
.
read_header
=
bmv_read_header
,
134
.
read_packet
=
bmv_read_packet
,
135
.
read_close
=
bmv_read_close
,
136
.extensions =
"bmv"
137
};