mosaico.c

来自「linux下的MPEG1」· C语言 代码 · 共 497 行 · 第 1/2 页

C
497
字号
  this->pip[param->pip_num - 1].x = param->x;  this->pip[param->pip_num - 1].y = param->y;  this->pip[param->pip_num - 1].w = param->w;  this->pip[param->pip_num - 1].h = param->h;  return 1;}static int mosaico_get_parameters(xine_post_t *this_gen, void *param_gen){  post_mosaico_t *this = (post_mosaico_t *)this_gen;  mosaico_parameters_t *param = (mosaico_parameters_t *)param_gen;    if (param->pip_num > this->pip_count || param->pip_num < 1)    param->pip_num = 1;  param->x = this->pip[param->pip_num - 1].x;  param->y = this->pip[param->pip_num - 1].y;  param->w = this->pip[param->pip_num - 1].w;  param->h = this->pip[param->pip_num - 1].h;  return 1;}static char *mosaico_get_help(void){  return _("Mosaico does simple picture in picture effects.\n"	   "\n"	   "Parameters\n"	   "  pip_num: the number of the picture slot the following settings apply to\n"	   "  x: the x coordinate of the left upper corner of the picture\n"	   "  y: the y coordinate of the left upper corner of the picture\n"	   "  w: the width of the picture\n"	   "  h: the height of the picture\n");}static void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream){  post_video_port_t *port = (post_video_port_t *)port_gen;  post_mosaico_t *this = (post_mosaico_t *)port->post;  vo_frame_t *free_frame;  int pip_num;  for (pip_num = 0; pip_num < this->pip_count; pip_num++)    if (this->post.xine_post.video_input[pip_num+1] == port_gen) break;    pthread_mutex_lock(&this->mutex);  free_frame = this->pip[pip_num].frame;  this->pip[pip_num].frame = NULL;  port->original_port->close(port->original_port, port->stream);  pthread_mutex_unlock(&this->mutex);  if (free_frame)    free_frame->free(free_frame);  port->stream = NULL;  _x_post_dec_usage(port);}static int mosaico_intercept_frame(post_video_port_t *port, vo_frame_t *frame){  /* TODO: only YV12 supported */  return (frame->format == XINE_IMGFMT_YV12);}static void frame_copy_content(vo_frame_t *to, vo_frame_t *from){  int size;  switch (from->format) {  case XINE_IMGFMT_YUY2:    /* TODO: implement conversion to YV12 or implement support to paste     * frames of different types together */    break;         case XINE_IMGFMT_YV12:    /* Y */    size = to->pitches[0] * to->height;       xine_fast_memcpy(to->base[0], from->base[0], size);    /* U */    size = to->pitches[1] * ((to->height + 1) / 2);    xine_fast_memcpy(to->base[1], from->base[1], size);    /* V */    size = to->pitches[2] * ((to->height + 1) / 2);    xine_fast_memcpy(to->base[2], from->base[2], size);  }}static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_num){  unsigned long target_width, target_height;  unsigned long source_width, source_height;  unsigned long background_width;  unsigned long scale_x, scale_y;  const int shift_x = 3, shift_y = 3;  unsigned long pos_x, pos_y, pos;  unsigned long target_offset, source_offset;  unsigned long i, j;  if (!this->pip[pip_num].frame) return;    target_width  = this->pip[pip_num].w;  target_height = this->pip[pip_num].h;  background_width = background->width;  source_width = this->pip[pip_num].frame->width;  source_height = this->pip[pip_num].frame->height;  scale_x = (source_width << shift_x) / target_width;  scale_y = (source_height << shift_y) / target_height;  pos_x = this->pip[pip_num].x;  pos_y = this->pip[pip_num].y;  pos = pos_y * background_width + pos_x;  switch (this->pip[pip_num].frame->format) {  case XINE_IMGFMT_YUY2:    /* TODO: implement YUY2 */    break;         case XINE_IMGFMT_YV12:    /* Y */    target_offset = 0;    for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))      for (i = 0; i < target_width; i++, target_offset++) {	source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);	background->base[0][pos + target_offset] = this->pip[pip_num].frame->base[0][source_offset];      }    background_width = (background_width + 1) / 2;    source_width = (source_width + 1) / 2;    pos_x = (pos_x + 1) / 2;    pos_y = (pos_y + 1) / 2;    pos = pos_y * background_width + pos_x;    target_width = (target_width + 1) / 2;    target_height = (target_height + 1) / 2;        /* U */    target_offset = 0;    for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))      for (i = 0; i < target_width; i++, target_offset++) {	source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);	background->base[1][pos + target_offset] = this->pip[pip_num].frame->base[1][source_offset];      }        /* V */    target_offset = 0;    for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))      for (i = 0; i < target_width; i++, target_offset++) {	source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);	background->base[2][pos + target_offset] = this->pip[pip_num].frame->base[2][source_offset];      }        break;  }}static int mosaico_draw_background(vo_frame_t *frame, xine_stream_t *stream){  post_video_port_t *port = (post_video_port_t *)frame->port;  post_mosaico_t *this = (post_mosaico_t *)port->post;  vo_frame_t *background;  int pip_num, skip;  pthread_mutex_lock(&this->mutex);    if (frame->bad_frame) {    _x_post_frame_copy_down(frame, frame->next);    skip = frame->next->draw(frame->next, stream);    _x_post_frame_copy_up(frame, frame->next);        this->vpts_limit = frame->vpts + frame->duration;    if (skip) {      this->skip      = skip;      this->skip_vpts = frame->vpts;    } else      this->skip      = 0;        pthread_mutex_unlock(&this->mutex);    pthread_cond_broadcast(&this->vpts_limit_changed);        return skip;  }    background = port->original_port->get_frame(port->original_port,    frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);  _x_post_frame_copy_down(frame, background);  frame_copy_content(background, frame);    for (pip_num = 0; pip_num < this->pip_count; pip_num++)    frame_paste(this, background, pip_num);    skip = background->draw(background, stream);  _x_post_frame_copy_up(frame, background);  this->vpts_limit = background->vpts + background->duration;  background->free(background);    if (skip) {    this->skip      = skip;    this->skip_vpts = frame->vpts;  } else    this->skip      = 0;    pthread_mutex_unlock(&this->mutex);  pthread_cond_broadcast(&this->vpts_limit_changed);    return skip;}static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream){  post_video_port_t *port = (post_video_port_t *)frame->port;  post_mosaico_t *this = (post_mosaico_t *)port->post;  vo_frame_t *free_frame;  int pip_num, skip;  for (pip_num = 0; pip_num < this->pip_count; pip_num++)    if (this->post.xine_post.video_input[pip_num+1] == frame->port) break;  _x_assert(pip_num < this->pip_count);    frame->lock(frame);    pthread_mutex_lock(&this->mutex);    /* the original output will never see this frame again */  _x_post_frame_u_turn(frame, stream);  while (frame->vpts > this->vpts_limit || !this->vpts_limit)    /* we are too early */    pthread_cond_wait(&this->vpts_limit_changed, &this->mutex);  free_frame = this->pip[pip_num].frame;  if (port->stream)    this->pip[pip_num].frame = frame;    if (this->skip && frame->vpts <= this->skip_vpts)    skip = this->skip;  else    skip = 0;    pthread_mutex_unlock(&this->mutex);  if (free_frame)    free_frame->free(free_frame);  if (!port->stream)    /* do not keep this frame when no stream is connected to us,     * otherwise, this frame might never get freed */    frame->free(frame);    return skip;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?