Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
smjpegenc.c
Go to the documentation of this file.
1
/*
2
* SMJPEG muxer
3
* Copyright (c) 2012 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
SMJPEGMuxContext
{
33
uint32_t
duration
;
34
}
SMJPEGMuxContext
;
35
36
static
int
smjpeg_write_header
(
AVFormatContext
*s)
37
{
38
AVDictionaryEntry
*
t
=
NULL
;
39
AVIOContext
*pb = s->
pb
;
40
int
n,
tag
;
41
42
if
(s->
nb_streams
> 2) {
43
av_log
(s,
AV_LOG_ERROR
,
"more than >2 streams are not supported\n"
);
44
return
AVERROR
(EINVAL);
45
}
46
avio_write
(pb,
SMJPEG_MAGIC
, 8);
47
avio_wb32
(pb, 0);
48
avio_wb32
(pb, 0);
49
50
while
((t =
av_dict_get
(s->
metadata
,
""
, t,
AV_DICT_IGNORE_SUFFIX
))) {
51
avio_wl32
(pb,
SMJPEG_TXT
);
52
avio_wb32
(pb, strlen(t->
key
) + strlen(t->
value
) + 3);
53
avio_write
(pb, t->
key
, strlen(t->
key
));
54
avio_write
(pb,
" = "
, 3);
55
avio_write
(pb, t->
value
, strlen(t->
value
));
56
}
57
58
for
(n = 0; n < s->
nb_streams
; n++) {
59
AVStream
*st = s->
streams
[n];
60
AVCodecContext
*codec = st->
codec
;
61
if
(codec->
codec_type
==
AVMEDIA_TYPE_AUDIO
) {
62
tag =
ff_codec_get_tag
(
ff_codec_smjpeg_audio_tags
, codec->
codec_id
);
63
if
(!tag) {
64
av_log
(s,
AV_LOG_ERROR
,
"unsupported audio codec\n"
);
65
return
AVERROR
(EINVAL);
66
}
67
avio_wl32
(pb,
SMJPEG_SND
);
68
avio_wb32
(pb, 8);
69
avio_wb16
(pb, codec->
sample_rate
);
70
avio_w8
(pb,
av_get_bits_per_sample
(codec->
codec_id
));
71
avio_w8
(pb, codec->
channels
);
72
avio_wl32
(pb, tag);
73
avpriv_set_pts_info
(st, 32, 1, 1000);
74
}
else
if
(codec->
codec_type
==
AVMEDIA_TYPE_VIDEO
) {
75
tag =
ff_codec_get_tag
(
ff_codec_smjpeg_video_tags
, codec->
codec_id
);
76
if
(!tag) {
77
av_log
(s,
AV_LOG_ERROR
,
"unsupported video codec\n"
);
78
return
AVERROR
(EINVAL);
79
}
80
avio_wl32
(pb,
SMJPEG_VID
);
81
avio_wb32
(pb, 12);
82
avio_wb32
(pb, 0);
83
avio_wb16
(pb, codec->
width
);
84
avio_wb16
(pb, codec->
height
);
85
avio_wl32
(pb, tag);
86
avpriv_set_pts_info
(st, 32, 1, 1000);
87
}
88
}
89
90
avio_wl32
(pb,
SMJPEG_HEND
);
91
avio_flush
(pb);
92
93
return
0;
94
}
95
96
static
int
smjpeg_write_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
97
{
98
SMJPEGMuxContext
*smc = s->
priv_data
;
99
AVIOContext
*pb = s->
pb
;
100
AVStream
*st = s->
streams
[pkt->
stream_index
];
101
AVCodecContext
*codec = st->
codec
;
102
103
if
(codec->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
104
avio_wl32
(pb,
SMJPEG_SNDD
);
105
else
if
(codec->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
106
avio_wl32
(pb,
SMJPEG_VIDD
);
107
else
108
return
0;
109
110
avio_wb32
(pb, pkt->
pts
);
111
avio_wb32
(pb, pkt->
size
);
112
avio_write
(pb, pkt->
data
, pkt->
size
);
113
avio_flush
(pb);
114
115
smc->
duration
=
FFMAX
(smc->
duration
, pkt->
pts
+ pkt->
duration
);
116
return
0;
117
}
118
119
static
int
smjpeg_write_trailer
(
AVFormatContext
*s)
120
{
121
SMJPEGMuxContext
*smc = s->
priv_data
;
122
AVIOContext
*pb = s->
pb
;
123
int64_t currentpos;
124
125
if
(pb->
seekable
) {
126
currentpos =
avio_tell
(pb);
127
avio_seek
(pb, 12, SEEK_SET);
128
avio_wb32
(pb, smc->
duration
);
129
avio_seek
(pb, currentpos, SEEK_SET);
130
}
131
132
avio_wl32
(pb,
SMJPEG_DONE
);
133
avio_flush
(pb);
134
135
return
0;
136
}
137
138
AVOutputFormat
ff_smjpeg_muxer
= {
139
.
name
=
"smjpeg"
,
140
.long_name =
NULL_IF_CONFIG_SMALL
(
"Loki SDL MJPEG"
),
141
.priv_data_size =
sizeof
(
SMJPEGMuxContext
),
142
.audio_codec =
CODEC_ID_PCM_S16LE
,
143
.video_codec =
CODEC_ID_MJPEG
,
144
.
write_header
=
smjpeg_write_header
,
145
.
write_packet
=
smjpeg_write_packet
,
146
.
write_trailer
=
smjpeg_write_trailer
,
147
.
flags
=
AVFMT_GLOBALHEADER
,
148
.codec_tag = (
const
AVCodecTag
*
const
[]){
ff_codec_smjpeg_video_tags
,
ff_codec_smjpeg_audio_tags
, 0 },
149
};