[MPlayer-dev-eng] [PATCH] adding yuv4mpeg output
Robert Kesterson
robertk at robertk.com
Fri Feb 1 22:40:39 CET 2002
Converting videos to VCD using mjpegtools requires getting the video into
yuv4mpeg format. This adds support for that format via a new "-vo
yuv4mpeg" command option. The output is written to "stream.yuv". This
makes it easy to have mplayer pump frames into an encoder by making a fifo
on stream.yuv, having mplayer pump frames into it, and having mpeg2enc
pull frames back out of it for encoding. (Use the "-benchmark" option to
mplayer for maximum speed if your CPU is quick at encoding.)
Add the vo_yuv4mpeg.c file to mplayer's libvo directory, apply the patch,
and rebuild. (Patch is against current mplayer CVS as of 1/31/02).
--
Robert Kesterson
robertk at robertk.com
-------------- next part --------------
? patch.txt
? libvo/vo_yuv4mpeg.c
Index: configure
===================================================================
RCS file: /cvsroot/mplayer/main/configure,v
retrieving revision 1.379
diff -u -r1.379 configure
--- configure 26 Jan 2002 00:47:26 -0000 1.379
+++ configure 1 Feb 2002 21:29:03 -0000
@@ -749,6 +749,7 @@
_3dfx=no
_tdfxfb=no
_directfb=auto
+_yuv4mpeg=yes
_zr=no
_largefiles=no
_vo2=no
@@ -857,6 +858,8 @@
--disable-tdfxfb) _tdfxfb=no ;;
--enable-directfb) _directfb=yes ;;
--disable-directfb) _directfb=no ;;
+ --enable-yuv4mpeg) _yuv4mpeg=yes ;;
+ --disable-yuv4mpeg) _yuv4mpeg=no ;;
--enable-zr) _zr=yes ;;
--disable-zr) _zr=no ;;
--enable-mtrr) _mtrr=yes ;;
@@ -1451,6 +1454,17 @@
fi
echores "$_directfb"
+echocheck "yuv4mpeg"
+if test "$_yuv4mpeg" = yes ; then
+ _def_yuv4mpeg='#define HAVE_YUV4MPEG 1'
+ _vosrc="$_vosrc vo_yuv4mpeg.c"
+ _vomodules="yuv4mpeg $_vomodules"
+else
+ _def_yuv4mpeg='#undef HAVE_YUV4MPEG'
+fi
+echores "$_yuv4mpeg"
+
+
# Checking for localization ...
echocheck "language"
@@ -3192,6 +3206,7 @@
$_def_3dfx
$_def_tdfxfb
$_def_directfb
+$_def_yuv4mpeg
$_def_zr
$_def_mga
$_def_xmga
Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.381
diff -u -r1.381 mplayer.c
--- mplayer.c 31 Jan 2002 09:57:13 -0000 1.381
+++ mplayer.c 1 Feb 2002 21:29:13 -0000
@@ -1058,7 +1058,13 @@
demuxer->file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h,
sh_video->fps,sh_video->frametime
);
-
+ vo_fps = sh_video->fps;
+ /* need to set fps here for output encoders to pick it up in their init */
+ if(force_fps){
+ sh_video->fps=force_fps;
+ sh_video->frametime=1.0f/sh_video->fps;
+ vo_fps = force_fps;
+ }
if(!sh_video->fps && !force_fps){
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_FPSnotspecified);
goto goto_next_file; // exit_player(MSGTR_Exit_error);
@@ -1455,6 +1461,7 @@
if(force_fps){
sh_video->fps=force_fps;
sh_video->frametime=1.0f/sh_video->fps;
+ vo_fps = force_fps;
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_FPSforced,sh_video->fps,sh_video->frametime);
}
Index: libvo/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/Makefile,v
retrieving revision 1.29
diff -u -r1.29 Makefile
--- libvo/Makefile 15 Jan 2002 12:13:53 -0000 1.29
+++ libvo/Makefile 1 Feb 2002 21:29:17 -0000
@@ -3,7 +3,7 @@
LIBNAME = libvo.a
-SRCS=aspect.c aclib.c osd.c font_load.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c x11_common.c $(OPTIONAL_SRCS) img_format.c sub.c
+SRCS=aspect.c aclib.c osd.c font_load.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c x11_common.c vo_yuv4mpeg.c $(OPTIONAL_SRCS) img_format.c sub.c
OBJS=$(SRCS:.c=.o)
ifeq ($(VIDIX),yes)
Index: libvo/video_out.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/video_out.c,v
retrieving revision 1.36
diff -u -r1.36 video_out.c
--- libvo/video_out.c 23 Jan 2002 16:54:29 -0000 1.36
+++ libvo/video_out.c 1 Feb 2002 21:29:17 -0000
@@ -83,6 +83,7 @@
extern vo_functions_t video_out_ggi;
extern vo_functions_t video_out_aa;
extern vo_functions_t video_out_mpegpes;
+extern vo_functions_t video_out_yuv4mpeg;
extern vo_functions_t video_out_dxr3;
#ifdef TARGET_LINUX
extern vo_functions_t video_out_vesa;
@@ -153,6 +154,7 @@
&video_out_pgm,
&video_out_md5,
&video_out_mpegpes,
+ &video_out_yuv4mpeg,
#if defined( ARCH_X86 ) && defined( TARGET_LINUX )
&video_out_vesa,
#endif
? ffmpeg/.new.Changelog
? libavcodec/.depend
? libavcodec/README
Index: libavcodec/Makefile
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/Makefile,v
retrieving revision 1.20
diff -u -r1.20 Makefile
Binary files /tmp/cvs9zhgxD and Makefile differ
-------------- next part --------------
/*
* vo_yuv4mpeg.c, yuv4mpeg (mjpegtools) interface
*
* Thrown together by
* Robert Kesterson <robertk at robertk.com>
* Based on the pgm output plugin, the rgb2rgb postproc filter, divxdec,
* and probably others.
*
* This is undoubtedly incomplete, inaccurate, or just plain wrong. :-)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/videodev.h>
LIBVO_EXTERN (yuv4mpeg)
static vo_info_t vo_info =
{
"yuv4mpeg output for mjpegtools (to \"stream.yuv\")",
"yuv4mpeg",
"Robert Kesterson <robertk at robertk.com>",
""
};
static int image_width;
static int image_height;
static uint8_t *image = NULL;
static uint8_t *image_y = NULL;
static uint8_t *image_u = NULL;
static uint8_t *image_v = NULL;
static int using_format = 0;
static FILE *yuv_out;
int write_bytes;
/**
*
* height should be a multiple of 2 and width should be a multiple of 2
* chrominance data is only taken from every secound line others are ignored
*/
#define RGB2YUV_SHIFT 8
#define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
#define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
#define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
#define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
#define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
#define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
#define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
#define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
#define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
static inline void rgb24toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
unsigned int width, unsigned int height,
unsigned int lumStride, unsigned int chromStride, unsigned int srcStride)
{
int y;
const int chromWidth= width>>1;
for(y=0; y<height; y+=2)
{
int i;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
udst[i] = U;
vdst[i] = V;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
ydst += lumStride;
src += srcStride;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
udst += chromStride;
vdst += chromStride;
ydst += lumStride;
src += srcStride;
}
}
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 *tuneinfo)
{
image_height = height;
image_width = width;
write_bytes = image_width * image_height * 3 / 2;
using_format = format;
image = malloc(write_bytes);
yuv_out = fopen("stream.yuv", "wb");
if (!yuv_out || image == NULL)
{
perror("Can't get memory or file handle to stream.yuv");
return -1;
}
image_y = image;
image_u = image_y + image_width * image_height;
image_v = image_u + (image_width * image_height) / 4;
// This isn't right.
// But it should work as long as the file isn't interlaced
// or otherwise unusual (the "Ip A0:0" part).
fprintf(yuv_out, "YUV4MPEG2 W%d H%d F%ld:%ld Ip A0:0\n",
image_width, image_height, (long)(vo_fps * 1000000.0), 1000000);
fflush(yuv_out);
return 0;
}
static const vo_info_t* get_info(void)
{
return &vo_info;
}
static void draw_osd(void)
{
}
static void flip_page (void)
{
fprintf(yuv_out, "FRAME\n");
if(fwrite(image, 1, write_bytes, yuv_out) != write_bytes)
perror("Error writing image to output!");
return;
}
static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y)
{
if(using_format == IMGFMT_YV12)
{
int i;
// copy Y:
uint8_t *dst = image_y + image_width * y + x;
uint8_t *src = srcimg[0];
for (i = 0; i < h; i++)
{
memcpy(dst, src, w);
src += stride[0];
dst += image_width;
}
{
// copy U + V:
uint8_t *src1 = srcimg[1];
uint8_t *src2 = srcimg[2];
uint8_t *dstu = image_u + image_width * (y / 2) + (x / 2);
uint8_t *dstv = image_v + image_width * (y / 2) + (x / 2);
for (i = 0; i < h / 2; i++)
{
memcpy(dstu, src1 , w / 2);
memcpy(dstv, src2, w / 2);
src1 += stride[1];
src2 += stride[2];
dstu += image_width / 2;
dstv += image_width / 2;
}
}
}
return 0;
}
static uint32_t draw_frame(uint8_t * src[])
{
switch(using_format)
{
case IMGFMT_YV12:
// gets done in draw_slice
break;
case IMGFMT_BGR|24:
{
#ifdef GUESS_THIS_ISNT_NEEDED
int c;
uint8_t temp;
//switch BGR to RGB
for(c = 0; c < image_width * image_height; c++)
{
temp = src[0][c * 3];
src[0][c * 3] = src[0][c * 3 + 2];
src[0][c * 3 + 2] = temp;
}
#endif
}
// intentional fall-through
case IMGFMT_RGB|24:
{
rgb24toyv12(src[0], image_y, image_u, image_v,
image_width, image_height,
image_width, image_width / 2, image_width * 3);
// RGB2YUV(image_width, image_height, src[0], image_y, image_u, image_v, 1);
}
break;
}
return 0;
}
static uint32_t query_format(uint32_t format)
{
switch(format){
case IMGFMT_YV12:
case IMGFMT_BGR|24:
case IMGFMT_RGB|24:
return 1;
}
return 0;
}
static void uninit(void)
{
if(image)
free(image);
image = NULL;
if(yuv_out)
fclose(yuv_out);
yuv_out = NULL;
}
static void check_events(void)
{
}
static uint32_t preinit(const char *arg)
{
return 0;
}
static void query_vaa(vo_vaa_t *vaa)
{
memset(vaa,0,sizeof(vo_vaa_t));
}
More information about the MPlayer-dev-eng
mailing list