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 03:58:44 for FFmpeg by
1.8.2