diff options
author | 2002-02-09 01:25:21 +0000 | |
---|---|---|
committer | 2002-02-09 01:25:21 +0000 | |
commit | 2f76bb1c0036d58308594b6264f8396a3e1c5983 (patch) | |
tree | c0857bc9a1a7f9a2420da3bb5c62500854dfa577 | |
parent | 4b33dccb25b75b3279c169c907eb14073c6114b4 (diff) |
yuv4mpeg output, by Robert Kesterson <robertk@robertk.com>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4598 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | libvo/vo_yuv4mpeg.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/libvo/vo_yuv4mpeg.c b/libvo/vo_yuv4mpeg.c new file mode 100644 index 0000000000..237292bf88 --- /dev/null +++ b/libvo/vo_yuv4mpeg.c @@ -0,0 +1,284 @@ +/* + * vo_yuv4mpeg.c, yuv4mpeg (mjpegtools) interface + * + * Thrown together by + * Robert Kesterson <robertk@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@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 uint32_t control(uint32_t request, void *data, ...) +{ + switch (request) { + case VOCTRL_QUERY_FORMAT: + return query_format(*((uint32_t*)data)); + } + return VO_NOTIMPL; +} |