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 + -
显示快捷键?