📄 video_output.c
字号:
if( ((i_y >= i_area_begin) && (i_y <= i_area_end)) || ((i_h >= i_area_begin) && (i_h <= i_area_end)) || ((i_y < i_area_begin) && (i_h > i_area_end)) ) { /* Keep the stripe above the picture, if any */ if( i_y < i_area_begin ) { SetBufferArea( p_vout, i_x, i_y, i_w, i_area_begin - i_y ); } /* Keep the stripe below the picture, if any */ if( i_h > i_area_end ) { SetBufferArea( p_vout, i_x, i_area_end, i_w, i_h - i_area_end ); } return; } } /* Skip some extensions until interesting areas */ for( i_area = 0; (i_area < p_buffer->i_areas) && (p_buffer->pi_area_end[i_area] + 1 <= i_y); i_area++ ) { ; } if( i_area == p_buffer->i_areas ) { /* New area is below all existing ones: just add it at the end of the * array, if possible - else, append it to the last one */ if( i_area < VOUT_MAX_AREAS ) { p_buffer->pi_area_begin[i_area] = i_y; p_buffer->pi_area_end[i_area] = i_h; p_buffer->i_areas++; } else {#ifdef DEBUG_VIDEO intf_DbgMsg("areas overflow\n");#endif p_buffer->pi_area_end[VOUT_MAX_AREAS - 1] = i_h; } } else { i_area_begin = p_buffer->pi_area_begin[i_area]; i_area_end = p_buffer->pi_area_end[i_area]; if( i_y < i_area_begin ) { if( i_h >= i_area_begin - 1 ) { /* Extend area above */ p_buffer->pi_area_begin[i_area] = i_y; } else { /* Create a new area above : merge last area if overflow, then * move all old areas down */ if( p_buffer->i_areas == VOUT_MAX_AREAS ) {#ifdef DEBUG_VIDEO intf_DbgMsg("areas overflow\n");#endif p_buffer->pi_area_end[VOUT_MAX_AREAS - 2] = p_buffer->pi_area_end[VOUT_MAX_AREAS - 1]; } else { p_buffer->i_areas++; } for( i_area_copy = p_buffer->i_areas - 1; i_area_copy > i_area; i_area_copy-- ) { p_buffer->pi_area_begin[i_area_copy] = p_buffer->pi_area_begin[i_area_copy - 1]; p_buffer->pi_area_end[i_area_copy] = p_buffer->pi_area_end[i_area_copy - 1]; } p_buffer->pi_area_begin[i_area] = i_y; p_buffer->pi_area_end[i_area] = i_h; return; } } if( i_h > i_area_end ) { /* Find further areas which can be merged with the new one */ for( i_area_copy = i_area + 1; (i_area_copy < p_buffer->i_areas) && (p_buffer->pi_area_begin[i_area] <= i_h); i_area_copy++ ) { ; } i_area_copy--; if( i_area_copy != i_area ) { /* Merge with last possible areas */ p_buffer->pi_area_end[i_area] = MAX( i_h, p_buffer->pi_area_end[i_area_copy] ); /* Shift lower areas upward */ i_area_shift = i_area_copy - i_area; p_buffer->i_areas -= i_area_shift; for( i_area_copy = i_area + 1; i_area_copy < p_buffer->i_areas; i_area_copy++ ) { p_buffer->pi_area_begin[i_area_copy] = p_buffer->pi_area_begin[i_area_copy + i_area_shift]; p_buffer->pi_area_end[i_area_copy] = p_buffer->pi_area_end[i_area_copy + i_area_shift]; } } else { /* Extend area below */ p_buffer->pi_area_end[i_area] = i_h; } } }}/***************************************************************************** * SetBufferPicture: clear buffer and set picture area ***************************************************************************** * This function is called before any rendering. It clears the current * rendering buffer and set the new picture area. If the picture pointer is * NULL, then no picture area is defined. Floating operations are avoided since * some MMX calculations may follow. *****************************************************************************/static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ){ vout_buffer_t * p_buffer; /* current buffer */ int i_pic_x, i_pic_y; /* picture position */ int i_pic_width, i_pic_height; /* picture dimensions */ int i_old_pic_y, i_old_pic_height; /* old picture area */ int i_vout_width, i_vout_height; /* display dimensions */ int i_area; /* area index */ int i_data_index; /* area data index */ int i_data_size; /* area data size, in 256 bytes blocs */ u64 * p_data; /* area data, for clearing */ byte_t * p_data8; /* area data, for clearing (slow) */ /* Choose buffer and set display dimensions */ p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ]; i_vout_width = p_vout->i_width; i_vout_height = p_vout->i_height; /* * Computes new picture size */ if( p_pic != NULL ) { /* Try horizontal scaling first - width must be a mutiple of 16 */ i_pic_width = (( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ? i_vout_width : p_pic->i_width) & ~0xf; switch( p_pic->i_aspect_ratio ) { case AR_3_4_PICTURE: i_pic_height = i_pic_width * 3 / 4; break; case AR_16_9_PICTURE: i_pic_height = i_pic_width * 9 / 16; break; case AR_221_1_PICTURE: i_pic_height = i_pic_width * 100 / 221; break; case AR_SQUARE_PICTURE: default: i_pic_height = p_pic->i_height * i_pic_width / p_pic->i_width; break; } /* If picture dimensions using horizontal scaling are too large, use * vertical scaling. Since width must be a multiple of 16, height is * adjusted again after. */ if( i_pic_height > i_vout_height ) { i_pic_height = ( p_vout->b_scale || (p_pic->i_height > i_vout_height)) ? i_vout_height : p_pic->i_height; switch( p_pic->i_aspect_ratio ) { case AR_3_4_PICTURE: i_pic_width = (i_pic_height * 4 / 3) & ~0xf; i_pic_height = i_pic_width * 3 / 4; break; case AR_16_9_PICTURE: i_pic_width = (i_pic_height * 16 / 9) & ~0xf; i_pic_height = i_pic_width * 9 / 16; break; case AR_221_1_PICTURE: i_pic_width = (i_pic_height * 221 / 100) & ~0xf; i_pic_height = i_pic_width * 100 / 221; break; case AR_SQUARE_PICTURE: default: i_pic_width = (p_pic->i_width * i_pic_height / p_pic->i_height) & ~0xf; i_pic_height = p_pic->i_height * i_pic_width / p_pic->i_width; break; } } /* Set picture position */ i_pic_x = (p_vout->i_width - i_pic_width) / 2; i_pic_y = (p_vout->i_height - i_pic_height) / 2; } else { /* No picture: size is 0 */ i_pic_x = 0; i_pic_y = 0; i_pic_width = 0; i_pic_height = 0; } /* * Set new picture size - if it is smaller than the previous one, clear * around it. Since picture are centered, only their size is tested. */ if( (p_buffer->i_pic_width > i_pic_width) || (p_buffer->i_pic_height > i_pic_height) ) { i_old_pic_y = p_buffer->i_pic_y; i_old_pic_height = p_buffer->i_pic_height; p_buffer->i_pic_x = i_pic_x; p_buffer->i_pic_y = i_pic_y; p_buffer->i_pic_width = i_pic_width; p_buffer->i_pic_height = i_pic_height; SetBufferArea( p_vout, 0, i_old_pic_y, p_vout->i_width, i_old_pic_height ); } else { p_buffer->i_pic_x = i_pic_x; p_buffer->i_pic_y = i_pic_y; p_buffer->i_pic_width = i_pic_width; p_buffer->i_pic_height = i_pic_height; } /* * Clear areas */ for( i_area = 0; i_area < p_buffer->i_areas; i_area++ ) {#ifdef DEBUG_VIDEO intf_DbgMsg("clearing picture %p area in buffer %d: %d-%d\n", p_pic, p_vout->i_buffer_index, p_buffer->pi_area_begin[i_area], p_buffer->pi_area_end[i_area] );#endif i_data_size = (p_buffer->pi_area_end[i_area] - p_buffer->pi_area_begin[i_area] + 1) * p_vout->i_bytes_per_line; p_data = (u64*) (p_buffer->p_data + p_vout->i_bytes_per_line * p_buffer->pi_area_begin[i_area]); for( i_data_index = i_data_size / 256; i_data_index-- ; ) { /* Clear 256 bytes block */ *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; *p_data++ = 0; } for( i_data_index = (i_data_size % 256) / 16; i_data_index--; ) { /* Clear remaining 16 bytes blocks */ *p_data++ = 0; *p_data++ = 0; } p_data8 = (byte_t *)p_data; for( i_data_index = i_data_size % 16; i_data_index--; ) { /* Clear remaining bytes */ *p_data8++ = 0; } } /* * Clear areas array */ p_buffer->i_areas = 0;}/***************************************************************************** * RenderPicture: render a picture ***************************************************************************** * This function convert a picture from a video heap to a pixel-encoded image * and copy it to the current rendering buffer. No lock is required, since the * rendered picture has been determined as existant, and will only be destroyed * by the vout thread later. *****************************************************************************/static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ){#ifdef DEBUG_VIDEO char psz_date[MSTRTIME_MAX_SIZE]; /* picture date */ mtime_t render_time; /* picture rendering time */#endif vout_buffer_t * p_buffer; /* rendering buffer */ byte_t * p_pic_data; /* convertion destination */ /* Get and set rendering informations */ p_buffer = &p_vout->p_buffer[ p_vout->i_buffer_index ]; p_pic_data = p_buffer->p_data + p_buffer->i_pic_x * p_vout->i_bytes_per_pixel + p_buffer->i_pic_y * p_vout->i_bytes_per_line;#ifdef DEBUG_VIDEO render_time = mdate();#endif /* * Choose appropriate rendering function and render picture */ switch( p_pic->i_type ) { case YUV_420_PICTURE: p_vout->yuv.p_Convert420( p_vout, p_pic_data, p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->i_width, p_pic->i_height, p_buffer->i_pic_width, p_buffer->i_pic_height, p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, p_pic->i_matrix_coefficients ); break; case YUV_422_PICTURE: p_vout->yuv.p_Convert422( p_vout, p_pic_data, p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->i_width, p_pic->i_height, p_buffer->i_pic_width, p_buffer->i_pic_height, p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel, p_pic->i_matrix_coefficients ); break; case YUV_444_PICTURE: p_vout->yuv.p_Convert444( p_vout, p_pic_data, p_pic->p_y, p_pic->p_u, p_pic->p_v, p_pic->i_width, p_pic->i_height, p_buffer->i_pic_width, p_buffer->i_pic_height, p_vout->i_bytes_per_line / p_vout->i_byt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -