summaryrefslogtreecommitdiff
path: root/src/video_out
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2009-01-02 18:00:01 +0000
committerReinhard Nißl <rnissl@gmx.de>2009-01-02 18:00:01 +0000
commitdb791923958fd4c72f75d4fede7aff189ff879a2 (patch)
tree42445acb47eba45f3015d44d1b5008ec227fbcc9 /src/video_out
parentfd02e4d93b00d02cf784018c274c26a142324003 (diff)
downloadxine-lib-db791923958fd4c72f75d4fede7aff189ff879a2.tar.gz
xine-lib-db791923958fd4c72f75d4fede7aff189ff879a2.tar.bz2
Add framegrabbing support; extend ARGB OSD interface.
Diffstat (limited to 'src/video_out')
-rw-r--r--src/video_out/video_out_vdpau.c168
1 files changed, 147 insertions, 21 deletions
diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c
index 857076869..e9f561579 100644
--- a/src/video_out/video_out_vdpau.c
+++ b/src/video_out/video_out_vdpau.c
@@ -216,6 +216,10 @@ typedef struct {
uint32_t argb_overlay_width;
uint32_t argb_overlay_height;
int has_argb_overlay;
+ int argb_osd_x;
+ int argb_osd_y;
+ int argb_osd_w;
+ int argb_osd_h;
VdpVideoSurface soft_surface;
uint32_t soft_surface_width;
@@ -280,33 +284,78 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over
-static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay )
+static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay )
{
vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
- if(overlay->argb_buffer == NULL)
+ if(overlay->argb_layer == NULL)
return 0;
- if ( (this->argb_overlay_width < overlay->width ) || (this->argb_overlay_height < overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) {
- if (this->argb_overlay != VDP_INVALID_HANDLE) {
- vdp_output_surface_destroy( this->argb_overlay );
+ pthread_mutex_lock(&overlay->argb_layer->mutex);
+
+ if (overlay->argb_layer->buffer != NULL) {
+ int extent_width = overlay->extent_width;
+ int extent_height = overlay->extent_height;
+ if (extent_width <= 0 || extent_height <= 0) {
+ extent_width = frame_gen->width;
+ extent_height = frame_gen->height;
}
- VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, &this->argb_overlay );
- if ( st != VDP_STATUS_OK ) {
- printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) );
+
+ if (extent_width > 0 && extent_height > 0) {
+ if ( (this->argb_overlay_width != extent_width ) || (this->argb_overlay_height != extent_height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) {
+ if (this->argb_overlay != VDP_INVALID_HANDLE) {
+ vdp_output_surface_destroy( this->argb_overlay );
+ }
+ VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, extent_width, extent_height, &this->argb_overlay );
+ if ( st != VDP_STATUS_OK ) {
+ printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) );
+ }
+ this->argb_overlay_width = extent_width;
+ this->argb_overlay_height = extent_height;
+
+ /* set stored osd location to extent as any smaller osd requires to clear the surface first */
+ this->argb_osd_x = 0;
+ this->argb_osd_y = 0;
+ this->argb_osd_w = extent_width;
+ this->argb_osd_h = extent_height;
+ }
+
+ /* wipe surface if osd layout changed */
+ if (overlay->x != this->argb_osd_x || overlay->y != this->argb_osd_y || overlay->width != this->argb_osd_w || overlay->height != this->argb_osd_h) {
+ this->argb_osd_x = overlay->x;
+ this->argb_osd_y = overlay->y;
+ this->argb_osd_w = overlay->width;
+ this->argb_osd_h = overlay->height;
+
+ uint32_t *zeros = calloc(4 * extent_width, extent_height);
+ if (zeros) {
+ uint32_t pitch = extent_width * 4;
+ VdpRect dest = { 0, 0, extent_width, extent_height };
+ VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(zeros), &pitch, &dest );
+ if ( st != VDP_STATUS_OK )
+ printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) );
+ free(zeros);
+ }
+ }
+
+ /* set destination area according to dirty area of argb layer and reset dirty area */
+ uint32_t pitch = overlay->width * 4;
+ uint32_t *buffer_start = overlay->argb_layer->buffer + overlay->argb_layer->y1 * overlay->width + overlay->argb_layer->x1;
+ VdpRect dest = { overlay->x + overlay->argb_layer->x1, overlay->y + overlay->argb_layer->y1, overlay->x + overlay->argb_layer->x2, overlay->y + overlay->argb_layer->y2 };
+ overlay->argb_layer->x1 = overlay->width;
+ overlay->argb_layer->y1 = overlay->height;
+ overlay->argb_layer->x2 = 0;
+ overlay->argb_layer->y2 = 0;
+
+ VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest );
+ if ( st != VDP_STATUS_OK ) {
+ printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) );
+ } else
+ this->has_argb_overlay = 1;
}
- this->argb_overlay_width = overlay->width;
- this->argb_overlay_height = overlay->height;
}
- uint32_t pitch = this->argb_overlay_width*4;
- VdpRect dest = { 0, overlay->y, this->argb_overlay_width, overlay->y + overlay->height };
- uint32_t *buffer_start = overlay->argb_buffer + overlay->y*this->argb_overlay_width;
- VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest );
- if ( st != VDP_STATUS_OK ) {
- printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) );
- } else
- this->has_argb_overlay = 1;
+ pthread_mutex_unlock(&overlay->argb_layer->mutex);
return 1;
}
@@ -418,8 +467,8 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v
++this->ovl_changed;
}
- if(overlay->argb_buffer)
- vdpau_process_argb_ovl( this, overlay );
+ if(overlay->argb_layer)
+ vdpau_process_argb_ovl( this, frame_gen, overlay );
}
@@ -603,6 +652,81 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen)
+static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_current_frame_data_t *data)
+{
+ vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
+ VdpStatus st;
+ VdpYCbCrFormat format;
+
+ if (this->vo_frame.format != XINE_IMGFMT_VDPAU) {
+ fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->vo_frame.format);
+ return;
+ }
+
+ if (!(this->flags & VO_CHROMA_422)) {
+ data->format = XINE_IMGFMT_YV12;
+ data->img_size = this->vo_frame.width * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2)
+ + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2);
+ if (data->img) {
+ this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 7) / 8);
+ this->vo_frame.pitches[1] = 8*((this->vo_frame.width + 15) / 16);
+ this->vo_frame.pitches[2] = 8*((this->vo_frame.width + 15) / 16);
+ this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]);
+ this->vo_frame.base[1] = xine_xmalloc_aligned(16, this->vo_frame.pitches[1] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[1]);
+ this->vo_frame.base[2] = xine_xmalloc_aligned(16, this->vo_frame.pitches[2] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[2]);
+ format = VDP_YCBCR_FORMAT_YV12;
+ }
+ } else {
+ data->format = XINE_IMGFMT_YUY2;
+ data->img_size = this->vo_frame.width * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height;
+ if (data->img) {
+ this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 3) / 4);
+ this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]);
+ format = VDP_YCBCR_FORMAT_YUYV;
+ }
+ }
+
+ if (data->img) {
+ st = vdp_video_surface_getbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);
+ if (st != VDP_STATUS_OK)
+ printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st));
+
+ if (format == VDP_YCBCR_FORMAT_YV12) {
+ yv12_to_yv12(
+ /* Y */
+ this->vo_frame.base[0], this->vo_frame.pitches[0],
+ data->img, this->vo_frame.width,
+ /* U */
+ this->vo_frame.base[1], this->vo_frame.pitches[1],
+ data->img+this->vo_frame.width*this->vo_frame.height, this->vo_frame.width/2,
+ /* V */
+ this->vo_frame.base[2], this->vo_frame.pitches[2],
+ data->img+this->vo_frame.width*this->vo_frame.height+this->vo_frame.width*this->vo_frame.height/4, this->vo_frame.width/2,
+ /* width x height */
+ this->vo_frame.width, this->vo_frame.height);
+ } else {
+ yuy2_to_yuy2(
+ /* src */
+ this->vo_frame.base[0], this->vo_frame.pitches[0],
+ /* dst */
+ data->img, this->vo_frame.width*2,
+ /* width x height */
+ this->vo_frame.width, this->vo_frame.height);
+ }
+
+ if (this->chunk[0])
+ free(this->chunk[0]);
+ if (this->chunk[1])
+ free(this->chunk[1]);
+ if (this->chunk[2])
+ free(this->chunk[2]);
+ this->chunk[0] = this->chunk[1] = this->chunk[2] = NULL;
+ }
+}
+
static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
{
vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
@@ -690,6 +814,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_
frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE;
--this->allocated_surfaces;
frame->vo_frame.proc_duplicate_frame_data = NULL;
+ frame->vo_frame.proc_provide_standard_frame_data = NULL;
}
}
@@ -701,6 +826,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_
frame->vdpau_accel_data.chroma = chroma;
++this->allocated_surfaces;
frame->vo_frame.proc_duplicate_frame_data = vdpau_duplicate_frame_data;
+ frame->vo_frame.proc_provide_standard_frame_data = vdpau_provide_standard_frame_data;
}
}
@@ -1504,7 +1630,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
return NULL;
}
- this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY;
+ this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY;
ok = 0;
uint32_t mw, mh, ml, mr;
st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh );