diff options
author | Reinhard Nißl <rnissl@gmx.de> | 2008-03-02 20:24:27 +0100 |
---|---|---|
committer | Reinhard Nißl <rnissl@gmx.de> | 2008-03-02 20:24:27 +0100 |
commit | c3247cea37ea7702703826df6b68a9754f9b8984 (patch) | |
tree | 3adc342997f995e97436a5dceda1e4ed1ba386ec /src | |
parent | d93c88ae06cd4452c8cfa5297def0f6e07c25fd5 (diff) | |
download | xine-lib-c3247cea37ea7702703826df6b68a9754f9b8984.tar.gz xine-lib-c3247cea37ea7702703826df6b68a9754f9b8984.tar.bz2 |
Provide safe and convenient implementations of xine_get_current_frame().
xine_get_current_frame() relies on the caller to provide a sufficiently
sized buffer. To calculate the required size of the buffer, one has to
call xine_get_current_frame() to retrieve the necessary parameters. But
as the image can change between two successive calls one has to pause
the stream for consistency.
To improve the situation, xine_get_current_frame_s() has been introduced
which requires to specify the buffer size when an image is going to be
retrieved. Furthermore, it will return the required/used buffer size.
In that way, it can prevent copying data into a too small buffer and
therefore can be considered safe.
For convenience, xine_get_current_frame_alloc() is provided which takes
care to allocate a sufficiently sized buffer. This function avoids
pausing the stream as the image will be returned in a single call.
Diffstat (limited to 'src')
-rw-r--r-- | src/xine-engine/xine.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 0558f2f81..fb2c08b04 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -1915,11 +1915,12 @@ int xine_get_pos_length (xine_stream_t *stream, int *pos_stream, return 1; } -int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, - int *ratio_code, int *format, - uint8_t *img) { +static int _x_get_current_frame_impl (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *size, int alloc_img) { vo_frame_t *frame; + int required_size; stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); @@ -1945,20 +1946,58 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, *format = frame->format; - if (img){ + switch (*format) { + + case XINE_IMGFMT_YV12: + required_size = *width * *height + + ((*width + 1) / 2) * ((*height + 1) / 2) + + ((*width + 1) / 2) * ((*height + 1) / 2); + break; + + case XINE_IMGFMT_YUY2: + required_size = *width * *height + + ((*width + 1) / 2) * *height + + ((*width + 1) / 2) * *height; + break; + + default: + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); + _x_abort (); + } + + if (alloc_img) { + /* return size if requested */ + if (size) + *size = required_size; + /* allocate img or fail */ + if (!(*img = xine_xmalloc (required_size))) + return 0; + } else { + /* fail if supplied buffer is to small */ + if (*img && size && *size < required_size) { + *size = required_size; + return 0; + } + /* return size if requested */ + if (size) + *size = required_size; + } + + if (*img) { switch (frame->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( /* Y */ frame->base[0], frame->pitches[0], - img, frame->width, + *img, frame->width, /* U */ frame->base[1], frame->pitches[1], - img+frame->width*frame->height, frame->width/2, + *img+frame->width*frame->height, frame->width/2, /* V */ frame->base[2], frame->pitches[2], - img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, + *img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, /* width x height */ frame->width, frame->height); break; @@ -1968,7 +2007,7 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, /* src */ frame->base[0], frame->pitches[0], /* dst */ - img, frame->width*2, + *img, frame->width*2, /* width x height */ frame->width, frame->height); break; @@ -1982,6 +2021,25 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, return 1; } +int xine_get_current_frame_alloc (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *size) { + uint8_t *no_img = NULL; + return _x_get_current_frame_impl(stream, width, height, ratio_code, format, img ? img : &no_img, size, img != NULL); +} + +int xine_get_current_frame_s (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img, int *size) { + return (!img || size) && _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, size, 0); +} + +int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img) { + return _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, NULL, 0); +} + int xine_get_video_frame (xine_stream_t *stream, int timestamp, /* msec */ int *width, int *height, |