Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
smjpegdec.c
Go to the documentation of this file.
1
/*
2
* SMJPEG demuxer
3
* Copyright (c) 2011 Paul B Mahol
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
27
#include "
avformat.h
"
28
#include "
internal.h
"
29
#include "
riff.h
"
30
#include "
smjpeg.h
"
31
32
typedef
struct
SMJPEGContext
{
33
int
audio_stream_index
;
34
int
video_stream_index
;
35
}
SMJPEGContext
;
36
37
static
int
smjpeg_probe
(
AVProbeData
*p)
38
{
39
if
(!memcmp(p->
buf
,
SMJPEG_MAGIC
, 8))
40
return
AVPROBE_SCORE_MAX
;
41
return
0;
42
}
43
44
static
int
smjpeg_read_header
(
AVFormatContext
*s,
AVFormatParameters
*ap)
45
{
46
SMJPEGContext
*sc = s->
priv_data
;
47
AVStream
*ast =
NULL
, *vst =
NULL
;
48
AVIOContext
*pb = s->
pb
;
49
uint32_t
version
, htype, hlength,
duration
;
50
char
*comment;
51
52
avio_skip
(pb, 8);
// magic
53
version =
avio_rb32
(pb);
54
if
(version)
55
av_log_ask_for_sample
(s,
"unknown version %d\n"
, version);
56
57
duration =
avio_rb32
(pb);
// in msec
58
59
while
(!pb->
eof_reached
) {
60
htype =
avio_rl32
(pb);
61
switch
(htype) {
62
case
SMJPEG_TXT
:
63
hlength =
avio_rb32
(pb);
64
if
(!hlength || hlength > 512)
65
return
AVERROR_INVALIDDATA
;
66
comment =
av_malloc
(hlength + 1);
67
if
(!comment)
68
return
AVERROR
(ENOMEM);
69
if
(
avio_read
(pb, comment, hlength) != hlength) {
70
av_freep
(&comment);
71
av_log
(s,
AV_LOG_ERROR
,
"error when reading comment\n"
);
72
return
AVERROR_INVALIDDATA
;
73
}
74
comment[hlength] = 0;
75
av_dict_set
(&s->
metadata
,
"comment"
, comment,
76
AV_DICT_DONT_STRDUP_VAL
);
77
break
;
78
case
SMJPEG_SND
:
79
if
(ast) {
80
av_log_ask_for_sample
(s,
"multiple audio streams not supported\n"
);
81
return
AVERROR_INVALIDDATA
;
82
}
83
hlength =
avio_rb32
(pb);
84
if
(hlength < 8)
85
return
AVERROR_INVALIDDATA
;
86
ast =
avformat_new_stream
(s, 0);
87
if
(!ast)
88
return
AVERROR
(ENOMEM);
89
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
90
ast->
codec
->
sample_rate
=
avio_rb16
(pb);
91
ast->
codec
->
bits_per_coded_sample
=
avio_r8
(pb);
92
ast->
codec
->
channels
=
avio_r8
(pb);
93
ast->
codec
->
codec_tag
=
avio_rl32
(pb);
94
ast->
codec
->
codec_id
=
ff_codec_get_id
(
ff_codec_smjpeg_audio_tags
,
95
ast->
codec
->
codec_tag
);
96
ast->
duration
=
duration
;
97
sc->
audio_stream_index
= ast->
index
;
98
avpriv_set_pts_info
(ast, 32, 1, 1000);
99
avio_skip
(pb, hlength - 8);
100
break
;
101
case
SMJPEG_VID
:
102
if
(vst) {
103
av_log_ask_for_sample
(s,
"multiple video streams not supported\n"
);
104
return
AVERROR_INVALIDDATA
;
105
}
106
hlength =
avio_rb32
(pb);
107
if
(hlength < 12)
108
return
AVERROR_INVALIDDATA
;
109
avio_skip
(pb, 4);
// number of frames
110
vst =
avformat_new_stream
(s, 0);
111
if
(!vst)
112
return
AVERROR
(ENOMEM);
113
vst->codec->codec_type =
AVMEDIA_TYPE_VIDEO
;
114
vst->codec->width =
avio_rb16
(pb);
115
vst->codec->height =
avio_rb16
(pb);
116
vst->codec->codec_tag =
avio_rl32
(pb);
117
vst->codec->codec_id =
ff_codec_get_id
(
ff_codec_smjpeg_video_tags
,
118
vst->codec->codec_tag);
119
vst->duration =
duration
;
120
sc->
video_stream_index
= vst->index;
121
avpriv_set_pts_info
(vst, 32, 1, 1000);
122
avio_skip
(pb, hlength - 12);
123
break
;
124
case
SMJPEG_HEND
:
125
return
0;
126
default
:
127
av_log
(s,
AV_LOG_ERROR
,
"unknown header %x\n"
, htype);
128
return
AVERROR_INVALIDDATA
;
129
}
130
}
131
132
return
AVERROR_EOF
;
133
}
134
135
static
int
smjpeg_read_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
136
{
137
SMJPEGContext
*sc = s->
priv_data
;
138
uint32_t dtype, ret,
size
, timestamp;
139
140
if
(s->
pb
->
eof_reached
)
141
return
AVERROR_EOF
;
142
dtype =
avio_rl32
(s->
pb
);
143
switch
(dtype) {
144
case
SMJPEG_SNDD
:
145
timestamp =
avio_rb32
(s->
pb
);
146
size =
avio_rb32
(s->
pb
);
147
ret =
av_get_packet
(s->
pb
, pkt, size);
148
pkt->
stream_index
= sc->
audio_stream_index
;
149
pkt->
pts
= timestamp;
150
break
;
151
case
SMJPEG_VIDD
:
152
timestamp =
avio_rb32
(s->
pb
);
153
size =
avio_rb32
(s->
pb
);
154
ret =
av_get_packet
(s->
pb
, pkt, size);
155
pkt->
stream_index
= sc->
video_stream_index
;
156
pkt->
pts
= timestamp;
157
break
;
158
case
SMJPEG_DONE
:
159
ret =
AVERROR_EOF
;
160
break
;
161
default
:
162
av_log
(s,
AV_LOG_ERROR
,
"unknown chunk %x\n"
, dtype);
163
ret =
AVERROR_INVALIDDATA
;
164
break
;
165
}
166
return
ret;
167
}
168
169
AVInputFormat
ff_smjpeg_demuxer
= {
170
.
name
=
"smjpeg"
,
171
.long_name =
NULL_IF_CONFIG_SMALL
(
"Loki SDL MJPEG"
),
172
.priv_data_size =
sizeof
(
SMJPEGContext
),
173
.
read_probe
=
smjpeg_probe
,
174
.
read_header
=
smjpeg_read_header
,
175
.
read_packet
=
smjpeg_read_packet
,
176
.extensions =
"mjpg"
,
177
};