FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
icoenc.c
Go to the documentation of this file.
1
/*
2
* Microsoft Windows ICO muxer
3
* Copyright (c) 2012 Michael Bradshaw <mjbshaw gmail com>
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg 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
* FFmpeg 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 FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
/**
23
* @file
24
* Microsoft Windows ICO muxer
25
*/
26
27
#include "
libavutil/intreadwrite.h
"
28
#include "
libavutil/pixdesc.h
"
29
#include "
avformat.h
"
30
31
typedef
struct
{
32
int
offset
;
33
int
size
;
34
unsigned
char
width
;
35
unsigned
char
height
;
36
short
bits
;
37
}
IcoImage
;
38
39
typedef
struct
{
40
int
current_image
;
41
int
nb_images
;
42
IcoImage
*
images
;
43
}
IcoMuxContext
;
44
45
static
int
ico_check_attributes
(
AVFormatContext
*
s
,
const
AVCodecContext
*
c
)
46
{
47
if
(c->
codec_id
==
AV_CODEC_ID_BMP
) {
48
if
(c->
pix_fmt
==
AV_PIX_FMT_PAL8
&&
AV_PIX_FMT_RGB32
!=
AV_PIX_FMT_BGRA
) {
49
av_log
(s,
AV_LOG_ERROR
,
"Wrong endianness for bmp pixel format\n"
);
50
return
AVERROR
(EINVAL);
51
}
else
if
(c->
pix_fmt
!=
AV_PIX_FMT_PAL8
&&
52
c->
pix_fmt
!=
AV_PIX_FMT_RGB555LE
&&
53
c->
pix_fmt
!=
AV_PIX_FMT_BGR24
&&
54
c->
pix_fmt
!=
AV_PIX_FMT_BGRA
) {
55
av_log
(s,
AV_LOG_ERROR
,
"BMP must be 1bit, 4bit, 8bit, 16bit, 24bit, or 32bit\n"
);
56
return
AVERROR
(EINVAL);
57
}
58
}
else
if
(c->
codec_id
==
AV_CODEC_ID_PNG
) {
59
if
(c->
pix_fmt
!=
AV_PIX_FMT_RGBA
) {
60
av_log
(s,
AV_LOG_ERROR
,
"PNG in ico requires pixel format to be rgba\n"
);
61
return
AVERROR
(EINVAL);
62
}
63
}
else
{
64
av_log
(s,
AV_LOG_ERROR
,
"Unsupported codec %s\n"
, c->
codec_name
);
65
return
AVERROR
(EINVAL);
66
}
67
68
if
(c->
width
> 256 ||
69
c->
height
> 256) {
70
av_log
(s,
AV_LOG_ERROR
,
"Unsupported dimensions %dx%d (dimensions cannot exceed 256x256)\n"
, c->
width
, c->
height
);
71
return
AVERROR
(EINVAL);
72
}
73
74
return
0;
75
}
76
77
static
int
ico_write_header
(
AVFormatContext
*
s
)
78
{
79
IcoMuxContext
*ico = s->
priv_data
;
80
AVIOContext
*pb = s->
pb
;
81
int
ret
;
82
int
i;
83
84
if
(!pb->
seekable
) {
85
av_log
(s,
AV_LOG_ERROR
,
"Output is not seekable\n"
);
86
return
AVERROR
(EINVAL);
87
}
88
89
ico->
current_image
= 0;
90
ico->
nb_images
= s->
nb_streams
;
91
92
avio_wl16
(pb, 0);
// reserved
93
avio_wl16
(pb, 1);
// 1 == icon
94
avio_skip
(pb, 2);
// skip the number of images
95
96
for
(i = 0; i < s->
nb_streams
; i++) {
97
if
(ret =
ico_check_attributes
(s, s->
streams
[i]->
codec
))
98
return
ret
;
99
100
// Fill in later when writing trailer...
101
avio_skip
(pb, 16);
102
}
103
104
ico->
images
=
av_mallocz
(ico->
nb_images
*
sizeof
(
IcoMuxContext
));
105
if
(!ico->
images
)
106
return
AVERROR
(ENOMEM);
107
108
avio_flush
(pb);
109
110
return
0;
111
}
112
113
static
int
ico_write_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
114
{
115
IcoMuxContext
*ico = s->
priv_data
;
116
IcoImage
*image;
117
AVIOContext
*pb = s->
pb
;
118
AVCodecContext
*
c
= s->
streams
[pkt->
stream_index
]->
codec
;
119
int
i;
120
121
if
(ico->
current_image
>= ico->
nb_images
) {
122
av_log
(s,
AV_LOG_ERROR
,
"ICO already contains %d images\n"
, ico->
current_image
);
123
return
AVERROR
(EIO);
124
}
125
126
image = &ico->
images
[ico->
current_image
++];
127
128
image->
offset
=
avio_tell
(pb);
129
image->
width
= (c->
width
== 256) ? 0 : c->
width
;
130
image->
height
= (c->
height
== 256) ? 0 : c->
height
;
131
132
if
(c->
codec_id
==
AV_CODEC_ID_PNG
) {
133
image->
bits
= c->
bits_per_coded_sample
;
134
image->
size
= pkt->
size
;
135
136
avio_write
(pb, pkt->
data
, pkt->
size
);
137
}
else
{
// BMP
138
if
(
AV_RL32
(pkt->
data
+ 14) != 40) {
// must be BITMAPINFOHEADER
139
av_log
(s,
AV_LOG_ERROR
,
"Invalid BMP\n"
);
140
return
AVERROR
(EINVAL);
141
}
142
143
image->
bits
=
AV_RL16
(pkt->
data
+ 28);
// allows things like 1bit and 4bit images to be preserved
144
image->
size
= pkt->
size
- 14 + c->
height
* (c->
width
+ 7) / 8;
145
146
avio_write
(pb, pkt->
data
+ 14, 8);
// Skip the BITMAPFILEHEADER header
147
avio_wl32
(pb,
AV_RL32
(pkt->
data
+ 22) * 2);
// rewrite height as 2 * height
148
avio_write
(pb, pkt->
data
+ 26, pkt->
size
- 26);
149
150
for
(i = 0; i < c->
height
* (c->
width
+ 7) / 8; ++i)
151
avio_w8
(pb, 0x00);
// Write bitmask (opaque)
152
}
153
154
return
0;
155
}
156
157
static
int
ico_write_trailer
(
AVFormatContext
*
s
)
158
{
159
IcoMuxContext
*ico = s->
priv_data
;
160
AVIOContext
*pb = s->
pb
;
161
int
i;
162
163
avio_seek
(pb, 4, SEEK_SET);
164
165
avio_wl16
(pb, ico->
current_image
);
166
167
for
(i = 0; i < ico->
nb_images
; i++) {
168
avio_w8
(pb, ico->
images
[i].
width
);
169
avio_w8
(pb, ico->
images
[i].
height
);
170
171
if
(s->
streams
[i]->
codec
->
codec_id
==
AV_CODEC_ID_BMP
&&
172
s->
streams
[i]->
codec
->
pix_fmt
==
AV_PIX_FMT_PAL8
) {
173
avio_w8
(pb, (ico->
images
[i].
bits
>= 8) ? 0 : 1 << ico->
images
[i].
bits
);
174
}
else
{
175
avio_w8
(pb, 0);
176
}
177
178
avio_w8
(pb, 0);
// reserved
179
avio_wl16
(pb, 1);
// color planes
180
avio_wl16
(pb, ico->
images
[i].
bits
);
181
avio_wl32
(pb, ico->
images
[i].
size
);
182
avio_wl32
(pb, ico->
images
[i].
offset
);
183
}
184
185
av_freep
(&ico->
images
);
186
187
return
0;
188
}
189
190
AVOutputFormat
ff_ico_muxer
= {
191
.
name
=
"ico"
,
192
.long_name =
NULL_IF_CONFIG_SMALL
(
"Microsoft Windows ICO"
),
193
.priv_data_size =
sizeof
(
IcoMuxContext
),
194
.mime_type =
"image/vnd.microsoft.icon"
,
195
.extensions =
"ico"
,
196
.audio_codec =
AV_CODEC_ID_NONE
,
197
.video_codec =
AV_CODEC_ID_BMP
,
198
.
write_header
=
ico_write_header
,
199
.
write_packet
=
ico_write_packet
,
200
.
write_trailer
=
ico_write_trailer
,
201
.
flags
=
AVFMT_NOTIMESTAMPS
,
202
};
Generated on Sun Mar 23 2014 23:50:11 for FFmpeg by
1.8.2