All pastes #838694 Raw Edit

Anonymous

public c v1 · immutable
#838694 ·published 2007-12-30 16:06 UTC
rendered paste body
/* * Copyright (C) 2007 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * * * video_out_raw.c, a video output plugin to pass raw data to frontend * * Written by Christophe Thommeret <hftom@free.fr>, * based on others video output plugins. * *//* #define LOG */#define LOG_MODULE "video_out_raw"#define NUM_FRAMES_BACKLOG   4	/* Allow thread some time to render frames */#define BYTES_PER_PIXEL 3#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <math.h>#include <errno.h>#include <ctype.h>#include <pthread.h>#include "xine.h"#include "video_out.h"#include "xine_internal.h"#include "yuv2rgb.h"#include "xineutils.h"typedef struct {  vo_frame_t         vo_frame;  int                width, height, format, flags;  double             ratio;  uint8_t           *chunk[4]; /* mem alloc by xmalloc_aligned           */  uint8_t           *rgb, *rgb_dst;  yuv2rgb_t         *yuv2rgb; /* yuv2rgb converter set up for this frame */} raw_frame_t;#define MAX_OVL_NUM 16typedef struct {  vo_driver_t        vo_driver;  void  *user_data;  void (*raw_output_cb) (void *user_data, void **frame_keeper, int format,    int frame_width, int frame_height, double frame_aspect,    void *data0, void *data1, void *data2);  void (*raw_overlay_cb) (void *user_data, int num_ovl,    raw_overlay_t *overlays_p);  void *current_frame;  int ovl_changed;  raw_overlay_t overlays[MAX_OVL_NUM];  int doYV12;  int doYUY2;  yuv2rgb_factory_t *yuv2rgb_factory;  /* Frame state */  raw_frame_t    *frame[NUM_FRAMES_BACKLOG];  xine_t            *xine;} raw_driver_t;typedef struct {  video_driver_class_t driver_class;  xine_t              *xine;} raw_class_t;static void raw_overlay_clut_yuv2rgb(raw_driver_t  *this, vo_overlay_t *overlay, raw_frame_t *frame){  int i;  clut_t* clut = (clut_t*) overlay->color;  if (!overlay->rgb_clut) {    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) {      *((uint32_t *)&clut[i]) = frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);    }    overlay->rgb_clut++;  }  if (!overlay->hili_rgb_clut) {    clut = (clut_t*) overlay->hili_color;    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {      *((uint32_t *)&clut[i]) = frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);    }    overlay->hili_rgb_clut++;  }}static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay ){  raw_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1];  if ( overlay->width<=0 || overlay->height<=0 )    return 0;  if ( ovl->in_use ) /* don't modify it while it's used by frontend */    return 1;  if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) )    ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 );  ovl->ovl_w = overlay->width;  ovl->ovl_h = overlay->height;  ovl->ovl_x = overlay->x;  ovl->ovl_y = overlay->y;  int num_rle = overlay->num_rle;  rle_elem_t *rle = overlay->rle;  uint8_t *rgba = ovl->ovl_rgba;  clut_t *low_colors = (clut_t*)overlay->color;  clut_t *hili_colors = (clut_t*)overlay->hili_color;  uint8_t *low_trans = overlay->trans;  uint8_t *hili_trans = overlay->hili_trans;  clut_t *colors;  uint8_t *trans;  uint8_t alpha;  int rlelen = 0;  uint8_t clr = 0;  int i, pos=0, x, y;  while ( num_rle>0 ) {    x = pos%ovl->ovl_w;    y = pos/ovl->ovl_w;    if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) {    	colors = hili_colors;    	trans = hili_trans;    }    else {    	colors = low_colors;    	trans = low_trans;    }    rlelen = rle->len;    clr = rle->color;    alpha = trans[clr];    for ( i=0; i<rlelen; ++i ) {    	rgba[0] = colors[clr].y;    	rgba[1] = colors[clr].cr;    	rgba[2] = colors[clr].cb;    	rgba[3] = alpha*255/15;    	rgba+= 4;    	++pos;    }    ++rle;    --num_rle;  }  ovl->in_use = 1;  return 1;}static void raw_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed){  raw_driver_t  *this = (raw_driver_t *) this_gen;  if ( !changed )  	return;  ++this->ovl_changed;}static void raw_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay){  raw_driver_t  *this = (raw_driver_t *) this_gen;  raw_frame_t *frame = (raw_frame_t *) frame_gen;  if ( !this->ovl_changed || this->ovl_changed>MAX_OVL_NUM )    return;  if (overlay->rle) {    if (!overlay->rgb_clut || !overlay->hili_rgb_clut)      raw_overlay_clut_yuv2rgb (this, overlay, frame);    if ( raw_process_ovl( this, overlay ) )      ++this->ovl_changed;  }}static void raw_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img){  raw_driver_t  *this = (raw_driver_t *) this_gen;  int i;  if ( !this->ovl_changed )    return;  this->raw_overlay_cb( this->user_data, this->ovl_changed-1, &this->overlays );  this->ovl_changed = 0;}static void raw_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src){  raw_frame_t  *frame = (raw_frame_t *) vo_img ;  vo_img->proc_called = 1;  if (! frame->rgb_dst)      return;  if( frame->vo_frame.crop_left || frame->vo_frame.crop_top ||      frame->vo_frame.crop_right || frame->vo_frame.crop_bottom )  {    /* TODO: opengl *could* support this?!? */    /* cropping will be performed by video_out.c */    return;  }  if (frame->format == XINE_IMGFMT_YV12)    frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]);  else    frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]);}static void raw_frame_field (vo_frame_t *vo_img, int which_field){  raw_frame_t  *frame = (raw_frame_t *) vo_img ;  raw_driver_t *this = (raw_driver_t *) vo_img->driver;  if ( frame->format==XINE_IMGFMT_YV12 && this->doYV12 ) {    frame->rgb_dst = 0;    return;  }  else if ( frame->format==XINE_IMGFMT_YUY2 && this->doYUY2 ) {    frame->rgb_dst = 0;    return;  }  switch (which_field) {  case VO_TOP_FIELD:    frame->rgb_dst    = (uint8_t *)frame->rgb;    break;  case VO_BOTTOM_FIELD:    frame->rgb_dst    = (uint8_t *)frame->rgb + frame->width * BYTES_PER_PIXEL;    break;  case VO_BOTH_FIELDS:    frame->rgb_dst    = (uint8_t *)frame->rgb;    break;  }  frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL);}static void raw_frame_dispose (vo_frame_t *vo_img){  raw_frame_t  *frame = (raw_frame_t *) vo_img ;  frame->yuv2rgb->dispose (frame->yuv2rgb);  free (frame->chunk[0]);  free (frame->chunk[1]);  free (frame->chunk[2]);  free (frame->chunk[3]);  free (frame);}static vo_frame_t *raw_alloc_frame (vo_driver_t *this_gen){  raw_frame_t  *frame;  raw_driver_t *this = (raw_driver_t *) this_gen;  frame = (raw_frame_t *) xine_xmalloc (sizeof (raw_frame_t));  if (!frame)    return NULL;  pthread_mutex_init (&frame->vo_frame.mutex, NULL);  /*   * supply required functions/fields   */  frame->vo_frame.proc_slice = raw_frame_proc_slice;  frame->vo_frame.proc_frame = NULL;  frame->vo_frame.field      = raw_frame_field;  frame->vo_frame.dispose    = raw_frame_dispose;  frame->vo_frame.driver     = this_gen;  /*   * colorspace converter for this frame   */  frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);  return (vo_frame_t *) frame;}static void raw_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen,      uint32_t width, uint32_t height, double ratio, int format, int flags){  raw_driver_t  *this = (raw_driver_t *) this_gen;  raw_frame_t   *frame = (raw_frame_t *) frame_gen;  /* Check frame size and format and reallocate if necessary */  if ((frame->width != width)      || (frame->height != height)      || (frame->format != format)      || (frame->flags  != flags)) {/*     lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */    flags &= VO_BOTH_FIELDS;    /* (re-) allocate render space */    free (frame->chunk[0]);    free (frame->chunk[1]);    free (frame->chunk[2]);    free (frame->chunk[3]);    if (format == XINE_IMGFMT_YV12) {      frame->vo_frame.pitches[0] = 8*((width + 7) / 8);      frame->vo_frame.pitches[1] = 8*((width + 15) / 16);      frame->vo_frame.pitches[2] = 8*((width + 15) / 16);      frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height,  (void **) &frame->chunk[0]);      frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]);      frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]);    } else {      frame->vo_frame.pitches[0] = 8*((width + 3) / 4);      frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);      frame->chunk[1] = NULL;      frame->chunk[2] = NULL;    }    frame->rgb = xine_xmalloc_aligned (16, BYTES_PER_PIXEL*width*height,				       (void **) &frame->chunk[3]);    /* set up colorspace converter */    switch (flags) {    case VO_TOP_FIELD:    case VO_BOTTOM_FIELD:      frame->yuv2rgb->configure (frame->yuv2rgb,				 width,				 height,				 2*frame->vo_frame.pitches[0],				 2*frame->vo_frame.pitches[1],				 width,				 height,				 BYTES_PER_PIXEL*width * 2);      break;    case VO_BOTH_FIELDS:      frame->yuv2rgb->configure (frame->yuv2rgb,				 width,				 height,				 frame->vo_frame.pitches[0],				 frame->vo_frame.pitches[1],				 width,				 height,				 BYTES_PER_PIXEL*width);      break;    }    frame->width = width;    frame->height = height;    frame->format = format;    raw_frame_field ((vo_frame_t *)frame, flags);  }  frame->ratio = ratio;}static int raw_redraw_needed (vo_driver_t *this_gen){  return 0;}static void raw_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen){  raw_driver_t  *this  = (raw_driver_t *) this_gen;  raw_frame_t   *frame = (raw_frame_t *) frame_gen;  int i;  if (this->frame[NUM_FRAMES_BACKLOG-1]) {    /*while ( this->current_frame ) {      printf("SLEEP\n");      this->raw_output_cb( this->user_data, &this->current_frame, 2, frame->width, frame->height, frame->ratio, 0, 0, 0 );      usleep(10000);    }*/    this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame.free (&this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame);  }  for (i = NUM_FRAMES_BACKLOG-1; i > 0; i--)    this->frame[i] = this->frame[i-1];  this->frame[0] = frame;  this->current_frame = frame;  if ( frame->rgb_dst ) {    this->raw_output_cb( this->user_data, &this->current_frame, 4, frame->width, frame->height, frame->ratio, frame->rgb, 0, 0 );  }  else if ( frame->format==XINE_IMGFMT_YV12 ) {    this->raw_output_cb( this->user_data, &this->current_frame, 1, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0],      frame->vo_frame.base[1], frame->vo_frame.base[2] );  }  else {    this->raw_output_cb( this->user_data, &this->current_frame, 2, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], 0, 0 );  }}static int raw_get_property (vo_driver_t *this_gen, int property){  raw_driver_t *this = (raw_driver_t *) this_gen;  switch (property) {  case VO_PROP_ASPECT_RATIO:    return XINE_VO_ASPECT_AUTO;  case VO_PROP_MAX_NUM_FRAMES:    return 15;  case VO_PROP_BRIGHTNESS:    return 0;  case VO_PROP_CONTRAST:    return 128;  case VO_PROP_SATURATION:    return 128;  case VO_PROP_WINDOW_WIDTH:    return 0;  case VO_PROP_WINDOW_HEIGHT:    return 0;  default:    return 0;  }}static int raw_set_property (vo_driver_t *this_gen, int property, int value){  return value;}static void raw_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max){  *min = 0;  *max = 0;}static int raw_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data){  return 0;}static uint32_t raw_get_capabilities (vo_driver_t *this_gen){  uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2;  return capabilities;}static void raw_dispose (vo_driver_t *this_gen){  raw_driver_t *this = (raw_driver_t *) this_gen;  int i;  for (i = 0; i < NUM_FRAMES_BACKLOG; i++)    if (this->frame[i])      this->frame[i]->vo_frame.dispose (&this->frame[i]->vo_frame);  this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);  for ( i=0; i<MAX_OVL_NUM; ++i )    free( this->overlays[i].ovl_rgba );  free (this);}static vo_driver_t *raw_open_plugin (video_driver_class_t *class_gen, const void *visual_gen){  raw_class_t       *class   = (raw_class_t *) class_gen;  raw_visual_t         *visual  = (raw_visual_t *) visual_gen;  raw_driver_t      *this;  int i;  this = (raw_driver_t *) xine_xmalloc (sizeof (raw_driver_t));  if (!this)    return NULL;  this->raw_output_cb  = visual->raw_output_cb;  this->user_data        = visual->user_data;  this->xine                = class->xine;  this->raw_overlay_cb = visual->raw_overlay_cb;  this->doYV12          = visual->supported_formats&1;  this->doYUY2          = visual->supported_formats&2;  this->vo_driver.get_capabilities     = raw_get_capabilities;  this->vo_driver.alloc_frame          = raw_alloc_frame;  this->vo_driver.update_frame_format  = raw_update_frame_format;  this->vo_driver.overlay_begin        = raw_overlay_begin;  this->vo_driver.overlay_blend        = raw_overlay_blend;  this->vo_driver.overlay_end          = raw_overlay_end;  this->vo_driver.display_frame        = raw_display_frame;  this->vo_driver.get_property         = raw_get_property;  this->vo_driver.set_property         = raw_set_property;  this->vo_driver.get_property_min_max = raw_get_property_min_max;  this->vo_driver.gui_data_exchange    = raw_gui_data_exchange;  this->vo_driver.dispose              = raw_dispose;  this->vo_driver.redraw_needed        = raw_redraw_needed;  this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL);  for (i = 0; i < NUM_FRAMES_BACKLOG; i++)    this->frame[i] = 0;  for ( i=0; i<MAX_OVL_NUM; ++i ) {    this->overlays[i].ovl_w = this->overlays[i].ovl_h = 2;    this->overlays[i].ovl_rgba = (uint8_t*)malloc(2*2*4);    this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0;    this->overlays[i].in_use = 0;  }  this->ovl_changed = 0;  this->current_frame = 0;  return &this->vo_driver;}/* * class functions */static char* raw_get_identifier (video_driver_class_t *this_gen){  return "raw";}static char* raw_get_description (video_driver_class_t *this_gen){  return _("xine video output plugin passing raw data to supplied callback");}static void raw_dispose_class (video_driver_class_t *this_gen){  raw_class_t *this = (raw_class_t *) this_gen;  free (this);}static void *raw_init_class (xine_t *xine, void *visual_gen){  raw_class_t *this = (raw_class_t *) xine_xmalloc (sizeof (raw_class_t));  this->driver_class.open_plugin     = raw_open_plugin;  this->driver_class.get_identifier  = raw_get_identifier;  this->driver_class.get_description = raw_get_description;  this->driver_class.dispose         = raw_dispose_class;  this->xine                         = xine;  return this;}static const vo_info_t vo_info_raw = {  7,                    /* priority    */  XINE_VISUAL_TYPE_RAW  /* visual type */};/* * exported plugin catalog entry */const plugin_info_t xine_plugin_info[] EXPORTED = {  /* type, API, "name", version, special_info, init_function */  { PLUGIN_VIDEO_OUT, 21, "raw", XINE_VERSION_CODE, &vo_info_raw, raw_init_class },  { PLUGIN_NONE, 0, "", 0, NULL, NULL }};