Mercurial > mplayer.hg
comparison libvo/vo_dxr3.c @ 4685:e8a749c866cf
Using the mplayer SwScaler instead of doing scaling manually (sometimes this dies with sig FPE
when not using -vc mpegpes with mpegs (I find it unlikely it would only happen on mpegs though))
Using detection code to check if using NTSC or PAL/SECAM and setting appropriate resolution and
GOP-Size based on this information. It now generates a valid mpeg1 stream instead of a hybrid
mpeg2 (with mpeg1 headers).
author | mswitch |
---|---|
date | Wed, 13 Feb 2002 00:38:23 +0000 |
parents | 8497da33a0d2 |
children | 93e959f0a6e4 |
comparison
equal
deleted
inserted
replaced
4684:db15e0ef6b31 | 4685:e8a749c866cf |
---|---|
4 * Copyright (C) 2002 David Holm <dholm@iname.com> | 4 * Copyright (C) 2002 David Holm <dholm@iname.com> |
5 * | 5 * |
6 */ | 6 */ |
7 | 7 |
8 /* ChangeLog added 2002-01-10 | 8 /* ChangeLog added 2002-01-10 |
9 * 2002-02-13: | |
10 * Using the swscaler instead of the old hand coded shit. (Checkout man mplayer and search for sws ;). | |
11 * Using aspect function to setup a proper mpeg1, no more hassling with odd resolutions or GOP-sizes, | |
12 * this would only create jitter on some vids! | |
13 * The swscaler sometimes exits with sig8 on mpegs, I don't know why yet (just use -vc mpegpes in this | |
14 * case, and report to me if you have any avi's etc which does this...) | |
15 * | |
9 * 2002-02-09: | 16 * 2002-02-09: |
10 * Thanks to the new control() method I have finally been able to enable the em8300 prebuffering. | 17 * Thanks to the new control() method I have finally been able to enable the em8300 prebuffering. |
11 * This should speed up playback on all systems, the vout cpu usage should rocket since I will be hogging | 18 * This should speed up playback on all systems, the vout cpu usage should rocket since I will be hogging |
12 * the pci bus. Not to worry though, since frames are prebuffered it should be able to take a few blows | 19 * the pci bus. Not to worry though, since frames are prebuffered it should be able to take a few blows |
13 * if you start doing other stuff simultaneously. | 20 * if you start doing other stuff simultaneously. |
33 | 40 |
34 #include <linux/em8300.h> | 41 #include <linux/em8300.h> |
35 #include <sys/ioctl.h> | 42 #include <sys/ioctl.h> |
36 #include <sys/stat.h> | 43 #include <sys/stat.h> |
37 #include <sys/types.h> | 44 #include <sys/types.h> |
45 #include <sys/select.h> | |
38 #include <unistd.h> | 46 #include <unistd.h> |
39 #include <stdio.h> | 47 #include <stdio.h> |
40 #include <stdlib.h> | 48 #include <stdlib.h> |
41 #include <string.h> | 49 #include <string.h> |
42 #include <fcntl.h> | 50 #include <fcntl.h> |
46 #include "config.h" | 54 #include "config.h" |
47 #include "fastmemcpy.h" | 55 #include "fastmemcpy.h" |
48 | 56 |
49 #include "video_out.h" | 57 #include "video_out.h" |
50 #include "video_out_internal.h" | 58 #include "video_out_internal.h" |
59 #include "aspect.h" | |
51 #include "../postproc/rgb2rgb.h" | 60 #include "../postproc/rgb2rgb.h" |
61 #include "../postproc/swscale.h" | |
52 | 62 |
53 #ifdef USE_LIBAVCODEC | 63 #ifdef USE_LIBAVCODEC |
54 #ifdef USE_LIBAVCODEC_SO | 64 #ifdef USE_LIBAVCODEC_SO |
55 #include <libffmpeg/avcodec.h> | 65 #include <libffmpeg/avcodec.h> |
56 #else | 66 #else |
77 static int s_pos_x, s_pos_y; | 87 static int s_pos_x, s_pos_y; |
78 static int d_pos_x, d_pos_y; | 88 static int d_pos_x, d_pos_y; |
79 static int osd_w, osd_h; | 89 static int osd_w, osd_h; |
80 static int noprebuf = 0; | 90 static int noprebuf = 0; |
81 static int img_format = 0; | 91 static int img_format = 0; |
92 static SwsContext * sws = NULL; | |
93 float scalefactor = 1.0; | |
82 | 94 |
83 /* File descriptors */ | 95 /* File descriptors */ |
84 static int fd_control = -1; | 96 static int fd_control = -1; |
85 static int fd_video = -1; | 97 static int fd_video = -1; |
86 static int fd_spu = -1; | 98 static int fd_spu = -1; |
136 } | 148 } |
137 } | 149 } |
138 return VO_NOTIMPL; | 150 return VO_NOTIMPL; |
139 } | 151 } |
140 | 152 |
141 static uint32_t config(uint32_t scr_width, uint32_t scr_height, uint32_t width, uint32_t height, uint32_t fullscreen, char *title, uint32_t format,const vo_tune_info_t *info) | 153 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format,const vo_tune_info_t *info) |
142 { | 154 { |
143 int tmp1, tmp2; | 155 int tmp1, tmp2; |
144 em8300_register_t reg; | 156 em8300_register_t reg; |
145 | 157 |
158 /* Softzoom turned on, downscale */ | |
146 /* This activates the subpicture processor, you can safely disable this and still send */ | 159 /* This activates the subpicture processor, you can safely disable this and still send */ |
147 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */ | 160 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */ |
148 /* up in a lockup */ | 161 /* up in a lockup */ |
149 ioval = EM8300_SPUMODE_ON; | 162 ioval = EM8300_SPUMODE_ON; |
150 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) { | 163 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) { |
178 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval); | 191 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval); |
179 } | 192 } |
180 | 193 |
181 /* Store some variables statically that we need later in another scope */ | 194 /* Store some variables statically that we need later in another scope */ |
182 img_format = format; | 195 img_format = format; |
183 v_width = scr_width; | 196 v_width = width; |
184 v_height = scr_height; | 197 v_height = height; |
185 | 198 |
186 /* libmp1e requires a width and height that is x|16 */ | 199 /* libavcodec requires a width and height that is x|16 */ |
187 s_width = (v_width + 15) / 16; | 200 aspect_save_orig(width, height); |
188 s_width *= 16; | 201 aspect_save_prescale(d_width, d_height); |
189 s_height = (v_height + 15) / 16; | 202 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval); |
190 s_height *= 16; | 203 if (ioval == EM8300_VIDEOMODE_NTSC) { |
204 printf("VO: [dxr3] Setting up for NTSC.\n"); | |
205 aspect_save_screenres(352, 240); | |
206 } else { | |
207 printf("VO: [dxr3] Setting up for PAL/SECAM.\n"); | |
208 aspect_save_screenres(352, 288); | |
209 } | |
210 aspect(&s_width, &s_height, A_ZOOM); | |
191 | 211 |
192 /* Try to figure out whether to use widescreen output or not */ | 212 /* Try to figure out whether to use widescreen output or not */ |
193 /* Anamorphic widescreen modes makes this a pain in the ass */ | 213 /* Anamorphic widescreen modes makes this a pain in the ass */ |
194 tmp1 = abs(height - ((width / 4) * 3)); | 214 tmp1 = abs(d_height - ((d_width / 4) * 3)); |
195 tmp2 = abs(height - (int) (width / 2.35)); | 215 tmp2 = abs(d_height - (int) (d_width / 2.35)); |
196 if (tmp1 < tmp2) { | 216 if (tmp1 < tmp2) { |
197 ioval = EM8300_ASPECTRATIO_4_3; | 217 ioval = EM8300_ASPECTRATIO_4_3; |
198 printf("VO: [dxr3] Setting aspect ratio to 4:3\n"); | 218 printf("VO: [dxr3] Setting aspect ratio to 4:3\n"); |
199 } else { | 219 } else { |
200 ioval = EM8300_ASPECTRATIO_16_9; | 220 ioval = EM8300_ASPECTRATIO_16_9; |
212 uninit(); | 232 uninit(); |
213 return -1; | 233 return -1; |
214 } | 234 } |
215 avc_context = malloc(sizeof(AVCodecContext)); | 235 avc_context = malloc(sizeof(AVCodecContext)); |
216 memset(avc_context, 0, sizeof(avc_context)); | 236 memset(avc_context, 0, sizeof(avc_context)); |
217 avc_context->width = v_width; | 237 avc_context->width = s_width; |
218 avc_context->height = v_height; | 238 avc_context->height = s_height; |
219 avc_context->frame_rate = 30 * FRAME_RATE_BASE; | 239 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval); |
220 avc_context->gop_size = 12; | 240 if (ioval == EM8300_VIDEOMODE_NTSC) { |
241 avc_context->gop_size = 18; | |
242 avc_context->frame_rate = 29.97 * FRAME_RATE_BASE; | |
243 } else { | |
244 avc_context->gop_size = 15; | |
245 avc_context->frame_rate = 25 * FRAME_RATE_BASE; | |
246 } | |
221 avc_context->bit_rate = 8e6; | 247 avc_context->bit_rate = 8e6; |
222 avc_context->flags = CODEC_FLAG_HQ | CODEC_FLAG_QSCALE; | 248 avc_context->flags = CODEC_FLAG_HQ | CODEC_FLAG_QSCALE; |
223 avc_context->quality = 2; | 249 avc_context->quality = 2; |
224 avc_context->pix_fmt = PIX_FMT_YUV420P; | 250 avc_context->pix_fmt = PIX_FMT_YUV420P; |
225 if (avcodec_open(avc_context, avc_codec) < 0) { | 251 if (avcodec_open(avc_context, avc_codec) < 0) { |
226 printf("VO: [dxr3] Unable to open codec\n"); | 252 printf("VO: [dxr3] Unable to open codec\n"); |
227 uninit(); | 253 uninit(); |
254 return -1; | |
255 } | |
256 | |
257 sws = getSwsContextFromCmdLine(v_width, v_height, img_format, s_width, s_height, IMGFMT_YV12); | |
258 if (!sws) | |
259 { | |
260 printf("vo_vesa: Can't initialize SwScaler\n"); | |
228 return -1; | 261 return -1; |
229 } | 262 } |
230 | 263 |
231 /* This stuff calculations the relative position of video and osd on screen */ | 264 /* This stuff calculations the relative position of video and osd on screen */ |
232 /* Old stuff taken from the dvb driver, should be removed when introducing spuenc */ | 265 /* Old stuff taken from the dvb driver, should be removed when introducing spuenc */ |
238 osd_w = s_width; | 271 osd_w = s_width; |
239 } else { | 272 } else { |
240 s_pos_x = 0; | 273 s_pos_x = 0; |
241 } | 274 } |
242 osd_h = s_height; | 275 osd_h = s_height; |
243 d_pos_y = (s_height - v_height) / 2; | 276 d_pos_y = (s_height - v_width) / 2; |
244 if (d_pos_y < 0) { | 277 if (d_pos_y < 0) { |
245 s_pos_y = -d_pos_y; | 278 s_pos_y = -d_pos_y; |
246 d_pos_y = 0; | 279 d_pos_y = 0; |
247 osd_h = s_height; | 280 osd_h = s_height; |
248 } else { | 281 } else { |
249 s_pos_y = 0; | 282 s_pos_y = 0; |
250 } | 283 } |
251 | 284 |
252 /* Create a pixel buffer and set up pointers for color components */ | 285 /* Create a pixel buffer and set up pointers for color components */ |
253 memset(&avc_picture, 0, sizeof(avc_picture)); | 286 memset(&avc_picture, 0, sizeof(avc_picture)); |
254 avc_picture.linesize[0] = v_width; | 287 avc_picture.linesize[0] = s_width; |
255 avc_picture.linesize[1] = v_width / 2; | 288 avc_picture.linesize[1] = s_width / 2; |
256 avc_picture.linesize[2] = v_width / 2; | 289 avc_picture.linesize[2] = s_width / 2; |
257 avc_outbuf = malloc(avc_outbuf_size); | 290 avc_outbuf = malloc(avc_outbuf_size); |
258 | 291 |
259 size = s_width * s_height; | 292 size = s_width * s_height; |
260 picture_buf = malloc((size * 3) / 2); | 293 picture_buf = malloc((size * 3) / 2); |
261 avc_picture.data[0] = picture_buf; | 294 avc_picture.data[0] = picture_buf; |
316 write(fd_video, p->data, p->size); | 349 write(fd_video, p->data, p->size); |
317 } | 350 } |
318 return 0; | 351 return 0; |
319 #ifdef USE_LIBAVCODEC | 352 #ifdef USE_LIBAVCODEC |
320 } else { | 353 } else { |
321 int size = s_width * s_height; | 354 int size, srcStride = (img_format == IMGFMT_YUY2) ? (v_width * 2) : (v_width * 3); |
322 if (img_format == IMGFMT_YUY2) { | 355 sws->swScale(sws, src, &srcStride, 0, v_height, avc_picture.data, avc_picture.linesize); |
323 yuy2toyv12(src[0], avc_picture.data[0], avc_picture.data[1], avc_picture.data[2], | |
324 v_width, v_height, avc_picture.linesize[0], avc_picture.linesize[1], v_width*2); | |
325 } else if (img_format == IMGFMT_BGR24) { | |
326 rgb24toyv12(src[0], avc_picture.data[0], avc_picture.data[1], avc_picture.data[2], | |
327 v_width, v_height, avc_picture.linesize[0], avc_picture.linesize[1], v_width*3); | |
328 } | |
329 draw_osd(); | 356 draw_osd(); |
330 size = avcodec_encode_video(avc_context, avc_outbuf, avc_outbuf_size, &avc_picture); | 357 size = avcodec_encode_video(avc_context, avc_outbuf, avc_outbuf_size, &avc_picture); |
331 write(fd_video, avc_outbuf, size); | 358 write(fd_video, avc_outbuf, size); |
332 return 0; | 359 return 0; |
333 #endif | 360 #endif |
335 return -1; | 362 return -1; |
336 } | 363 } |
337 | 364 |
338 static void flip_page(void) | 365 static void flip_page(void) |
339 { | 366 { |
367 fd_set rfds; | |
368 struct timeval tv; | |
340 #ifdef USE_LIBAVCODEC | 369 #ifdef USE_LIBAVCODEC |
341 if (img_format == IMGFMT_YV12) { | 370 if (img_format == IMGFMT_YV12) { |
342 int out_size = avcodec_encode_video(avc_context, avc_outbuf, avc_outbuf_size, &avc_picture); | 371 int out_size = avcodec_encode_video(avc_context, avc_outbuf, avc_outbuf_size, &avc_picture); |
343 if (!noprebuf) { | 372 if (!noprebuf) { |
344 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts); | 373 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts); |
345 } | 374 } |
346 write(fd_video, avc_outbuf, out_size); | 375 write(fd_video, avc_outbuf, out_size); |
347 } | 376 } |
348 #endif | 377 #endif |
378 tv.tv_sec = 0; | |
379 tv.tv_usec = 1e6 / floor(vo_fps); | |
380 FD_ZERO(&rfds); | |
381 FD_SET(fd_video, &rfds); | |
382 select(fd_video + 1, NULL, &rfds, NULL, &tv); | |
349 } | 383 } |
350 | 384 |
351 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0) | 385 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0) |
352 { | 386 { |
353 #ifdef USE_LIBAVCODEC | 387 #ifdef USE_LIBAVCODEC |
354 if (img_format == IMGFMT_YV12) { | 388 if (img_format == IMGFMT_YV12) { |
355 int y; | 389 sws->swScale(sws, srcimg, stride, y0, h, avc_picture.data, avc_picture.linesize); |
356 unsigned char *s, *s1; | |
357 unsigned char *d, *d1; | |
358 | |
359 x0 += d_pos_x; | |
360 y0 += d_pos_y; | |
361 | |
362 if ((x0 + w) > avc_picture.linesize[0]) { | |
363 w = avc_picture.linesize[0] - x0; | |
364 } | |
365 if ((y0 + h) > s_height) { | |
366 h = s_height - y0; | |
367 } | |
368 | |
369 s = srcimg[0] + s_pos_x + s_pos_y * stride[0]; | |
370 d = avc_picture.data[0] + x0 + y0 * avc_picture.linesize[0]; | |
371 for(y = 0; y < h; y++) { | |
372 memcpy(d, s, w); | |
373 s += stride[0]; | |
374 d += avc_picture.linesize[0]; | |
375 } | |
376 | |
377 w /= 2; | |
378 h /= 2; | |
379 x0 /= 2; | |
380 y0 /= 2; | |
381 | |
382 s = srcimg[1] + s_pos_x + (s_pos_y * stride[1]); | |
383 d = avc_picture.data[1] + x0 + (y0 * avc_picture.linesize[1]); | |
384 s1 = srcimg[2] + s_pos_x + (s_pos_y * stride[2]); | |
385 d1 = avc_picture.data[2] + x0 + (y0 * avc_picture.linesize[2]); | |
386 for(y = 0; y < h; y++) { | |
387 memcpy(d, s, w); | |
388 memcpy(d1, s1, w); | |
389 s += stride[1]; | |
390 s1 += stride[2]; | |
391 d += avc_picture.linesize[1]; | |
392 d1 += avc_picture.linesize[2]; | |
393 } | |
394 return 0; | 390 return 0; |
395 } | 391 } |
396 #endif | 392 #endif |
397 return -1; | 393 return -1; |
398 } | 394 } |
399 | 395 |
400 static void uninit(void) | 396 static void uninit(void) |
401 { | 397 { |
402 printf("VO: [dxr3] Uninitializing\n"); | 398 printf("VO: [dxr3] Uninitializing\n"); |
399 if (sws) { | |
400 freeSwsContext(sws); | |
401 } | |
403 #ifdef USE_LIBAVCODEC | 402 #ifdef USE_LIBAVCODEC |
404 if (avc_context) { | 403 if (avc_context) { |
405 avcodec_close(avc_context); | 404 avcodec_close(avc_context); |
406 } | 405 } |
407 if (picture_buf) { | 406 if (picture_buf) { |