FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavdevice
sdl.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Stefano Sabatini
3
*
4
* This file is part of FFmpeg.
5
*
6
* FFmpeg is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* FFmpeg is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with FFmpeg; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
/**
22
* @file
23
* libSDL output device
24
*/
25
26
#include <SDL.h>
27
#include "
libavutil/avstring.h
"
28
#include "
libavutil/opt.h
"
29
#include "
libavutil/parseutils.h
"
30
#include "
libavutil/pixdesc.h
"
31
#include "
avdevice.h
"
32
33
typedef
struct
{
34
AVClass
*
class
;
35
SDL_Surface *
surface
;
36
SDL_Overlay *
overlay
;
37
char
*
window_title
;
38
char
*
icon_title
;
39
int
window_width
, window_height;
/**< size of the window */
40
int
overlay_width
, overlay_height;
/**< size of the video in the window */
41
int
overlay_x,
overlay_y
;
42
int
overlay_fmt
;
43
int
sdl_was_already_inited
;
44
}
SDLContext
;
45
46
static
const
struct
sdl_overlay_pix_fmt_entry
{
47
enum
AVPixelFormat
pix_fmt
;
int
overlay_fmt
;
48
}
sdl_overlay_pix_fmt_map
[] = {
49
{
AV_PIX_FMT_YUV420P
, SDL_IYUV_OVERLAY },
50
{
AV_PIX_FMT_YUYV422
, SDL_YUY2_OVERLAY },
51
{
AV_PIX_FMT_UYVY422
, SDL_UYVY_OVERLAY },
52
{
AV_PIX_FMT_NONE
, 0 },
53
};
54
55
static
int
sdl_write_trailer
(
AVFormatContext
*s)
56
{
57
SDLContext
*sdl = s->
priv_data
;
58
59
av_freep
(&sdl->
window_title
);
60
av_freep
(&sdl->
icon_title
);
61
62
if
(sdl->
overlay
) {
63
SDL_FreeYUVOverlay(sdl->
overlay
);
64
sdl->
overlay
=
NULL
;
65
}
66
if
(!sdl->
sdl_was_already_inited
)
67
SDL_Quit();
68
69
return
0;
70
}
71
72
static
int
sdl_write_header
(
AVFormatContext
*s)
73
{
74
SDLContext
*sdl = s->
priv_data
;
75
AVStream
*st = s->
streams
[0];
76
AVCodecContext
*encctx = st->
codec
;
77
AVRational
sar, dar;
/* sample and display aspect ratios */
78
int
i, ret;
79
80
if
(!sdl->
window_title
)
81
sdl->
window_title
=
av_strdup
(s->
filename
);
82
if
(!sdl->
icon_title
)
83
sdl->
icon_title
=
av_strdup
(sdl->
window_title
);
84
85
if
(SDL_WasInit(SDL_INIT_VIDEO)) {
86
av_log
(s,
AV_LOG_ERROR
,
87
"SDL video subsystem was already inited, aborting\n"
);
88
sdl->
sdl_was_already_inited
= 1;
89
ret =
AVERROR
(EINVAL);
90
goto
fail;
91
}
92
93
if
(SDL_Init(SDL_INIT_VIDEO) != 0) {
94
av_log
(s,
AV_LOG_ERROR
,
"Unable to initialize SDL: %s\n"
, SDL_GetError());
95
ret =
AVERROR
(EINVAL);
96
goto
fail;
97
}
98
99
if
( s->
nb_streams
> 1
100
|| encctx->
codec_type
!=
AVMEDIA_TYPE_VIDEO
101
|| encctx->
codec_id
!=
AV_CODEC_ID_RAWVIDEO
) {
102
av_log
(s,
AV_LOG_ERROR
,
"Only supports one rawvideo stream\n"
);
103
ret =
AVERROR
(EINVAL);
104
goto
fail;
105
}
106
107
for
(i = 0;
sdl_overlay_pix_fmt_map
[i].
pix_fmt
!=
AV_PIX_FMT_NONE
; i++) {
108
if
(
sdl_overlay_pix_fmt_map
[i].
pix_fmt
== encctx->
pix_fmt
) {
109
sdl->
overlay_fmt
=
sdl_overlay_pix_fmt_map
[i].
overlay_fmt
;
110
break
;
111
}
112
}
113
114
if
(!sdl->
overlay_fmt
) {
115
av_log
(s,
AV_LOG_ERROR
,
116
"Unsupported pixel format '%s', choose one of yuv420p, yuyv422, or uyvy422\n"
,
117
av_get_pix_fmt_name
(encctx->
pix_fmt
));
118
ret =
AVERROR
(EINVAL);
119
goto
fail;
120
}
121
122
/* compute overlay width and height from the codec context information */
123
sar = st->
sample_aspect_ratio
.
num
? st->
sample_aspect_ratio
: (
AVRational
){ 1, 1 };
124
dar =
av_mul_q
(sar, (
AVRational
){ encctx->
width
, encctx->
height
});
125
126
/* we suppose the screen has a 1/1 sample aspect ratio */
127
if
(sdl->
window_width
&& sdl->
window_height
) {
128
/* fit in the window */
129
if
(
av_cmp_q
(dar, (
AVRational
){ sdl->
window_width
, sdl->
window_height
}) > 0) {
130
/* fit in width */
131
sdl->
overlay_width
= sdl->
window_width
;
132
sdl->
overlay_height
=
av_rescale
(sdl->
overlay_width
, dar.
den
, dar.
num
);
133
}
else
{
134
/* fit in height */
135
sdl->
overlay_height
= sdl->
window_height
;
136
sdl->
overlay_width
=
av_rescale
(sdl->
overlay_height
, dar.
num
, dar.
den
);
137
}
138
}
else
{
139
if
(sar.
num
> sar.
den
) {
140
sdl->
overlay_width
= encctx->
width
;
141
sdl->
overlay_height
=
av_rescale
(sdl->
overlay_width
, dar.
den
, dar.
num
);
142
}
else
{
143
sdl->
overlay_height
= encctx->
height
;
144
sdl->
overlay_width
=
av_rescale
(sdl->
overlay_height
, dar.
num
, dar.
den
);
145
}
146
sdl->
window_width
= sdl->
overlay_width
;
147
sdl->
window_height
= sdl->
overlay_height
;
148
}
149
sdl->
overlay_x
= (sdl->
window_width
- sdl->
overlay_width
) / 2;
150
sdl->
overlay_y
= (sdl->
window_height
- sdl->
overlay_height
) / 2;
151
152
SDL_WM_SetCaption(sdl->
window_title
, sdl->
icon_title
);
153
sdl->
surface
= SDL_SetVideoMode(sdl->
window_width
, sdl->
window_height
,
154
24, SDL_SWSURFACE);
155
if
(!sdl->
surface
) {
156
av_log
(s,
AV_LOG_ERROR
,
"Unable to set video mode: %s\n"
, SDL_GetError());
157
ret =
AVERROR
(EINVAL);
158
goto
fail;
159
}
160
161
sdl->
overlay
= SDL_CreateYUVOverlay(encctx->
width
, encctx->
height
,
162
sdl->
overlay_fmt
, sdl->
surface
);
163
if
(!sdl->
overlay
|| sdl->
overlay
->pitches[0] < encctx->
width
) {
164
av_log
(s,
AV_LOG_ERROR
,
165
"SDL does not support an overlay with size of %dx%d pixels\n"
,
166
encctx->
width
, encctx->
height
);
167
ret =
AVERROR
(EINVAL);
168
goto
fail;
169
}
170
171
av_log
(s,
AV_LOG_VERBOSE
,
"w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d\n"
,
172
encctx->
width
, encctx->
height
,
av_get_pix_fmt_name
(encctx->
pix_fmt
), sar.
num
, sar.
den
,
173
sdl->
overlay_width
, sdl->
overlay_height
);
174
return
0;
175
176
fail:
177
sdl_write_trailer
(s);
178
return
ret;
179
}
180
181
static
int
sdl_write_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
182
{
183
SDLContext
*sdl = s->
priv_data
;
184
AVCodecContext
*encctx = s->
streams
[0]->
codec
;
185
SDL_Rect
rect
= { sdl->
overlay_x
, sdl->
overlay_y
, sdl->
overlay_width
, sdl->
overlay_height
};
186
AVPicture
pict;
187
int
i;
188
189
avpicture_fill
(&pict, pkt->
data
, encctx->
pix_fmt
, encctx->
width
, encctx->
height
);
190
191
SDL_FillRect(sdl->
surface
, &sdl->
surface
->clip_rect,
192
SDL_MapRGB(sdl->
surface
->format, 0, 0, 0));
193
SDL_LockYUVOverlay(sdl->
overlay
);
194
for
(i = 0; i < 3; i++) {
195
sdl->
overlay
->pixels [i] = pict.
data
[i];
196
sdl->
overlay
->pitches[i] = pict.
linesize
[i];
197
}
198
SDL_DisplayYUVOverlay(sdl->
overlay
, &rect);
199
SDL_UnlockYUVOverlay(sdl->
overlay
);
200
201
SDL_UpdateRect(sdl->
surface
, rect.x, rect.y, rect.w, rect.h);
202
203
return
0;
204
}
205
206
#define OFFSET(x) offsetof(SDLContext,x)
207
208
static
const
AVOption
options
[] = {
209
{
"window_title"
,
"set SDL window title"
,
OFFSET
(
window_title
),
AV_OPT_TYPE_STRING
, {.str =
NULL
}, 0, 0,
AV_OPT_FLAG_ENCODING_PARAM
},
210
{
"icon_title"
,
"set SDL iconified window title"
,
OFFSET
(icon_title) ,
AV_OPT_TYPE_STRING
, {.str =
NULL
}, 0, 0,
AV_OPT_FLAG_ENCODING_PARAM
},
211
{
"window_size"
,
"set SDL window forced size"
,
OFFSET
(window_width),
AV_OPT_TYPE_IMAGE_SIZE
,{.str=
NULL
}, 0, 0,
AV_OPT_FLAG_ENCODING_PARAM
},
212
{
NULL
},
213
};
214
215
static
const
AVClass
sdl_class
= {
216
.
class_name
=
"sdl outdev"
,
217
.item_name =
av_default_item_name
,
218
.option =
options
,
219
.version =
LIBAVUTIL_VERSION_INT
,
220
};
221
222
AVOutputFormat
ff_sdl_muxer
= {
223
.
name
=
"sdl"
,
224
.long_name =
NULL_IF_CONFIG_SMALL
(
"SDL output device"
),
225
.priv_data_size =
sizeof
(
SDLContext
),
226
.audio_codec =
AV_CODEC_ID_NONE
,
227
.video_codec =
AV_CODEC_ID_RAWVIDEO
,
228
.
write_header
=
sdl_write_header
,
229
.
write_packet
=
sdl_write_packet
,
230
.
write_trailer
=
sdl_write_trailer
,
231
.
flags
=
AVFMT_NOFILE
|
AVFMT_VARIABLE_FPS
|
AVFMT_NOTIMESTAMPS
,
232
.priv_class = &sdl_class,
233
};
Generated on Sat May 25 2013 04:01:14 for FFmpeg by
1.8.2