You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by mj...@apache.org on 2016/03/20 03:24:37 UTC
[07/50] incubator-guacamole-server git commit: GUAC-236: Maintain
aspect ratio by adding letterboxes / pillarboxes as necessary.
GUAC-236: Maintain aspect ratio by adding letterboxes / pillarboxes as necessary.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/8ed0cd5f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/8ed0cd5f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/8ed0cd5f
Branch: refs/heads/master
Commit: 8ed0cd5f16fdeec3c9d841801ad04c3b45aa7c0d
Parents: 2798536
Author: Michael Jumper <mi...@guac-dev.org>
Authored: Sat Mar 12 21:46:45 2016 -0800
Committer: Michael Jumper <mi...@guac-dev.org>
Committed: Mon Mar 14 20:22:04 2016 -0700
----------------------------------------------------------------------
src/guacenc/video.c | 101 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 88 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/8ed0cd5f/src/guacenc/video.c
----------------------------------------------------------------------
diff --git a/src/guacenc/video.c b/src/guacenc/video.c
index 7c6c0c2..fbf02e0 100644
--- a/src/guacenc/video.c
+++ b/src/guacenc/video.c
@@ -255,18 +255,39 @@ int guacenc_video_advance_timeline(guacenc_video* video,
/**
* Converts the given Guacamole video encoder buffer to a frame in the format
- * required by libavcodec / libswscale. No scaling is performed; the image data
- * is copied verbatim.
+ * required by libavcodec / libswscale. Black margins of the specified sizes
+ * will be added. No scaling is performed; the image data is copied verbatim.
*
* @param buffer
* The guacenc_buffer to copy as a new AVFrame.
*
+ * @param lsize
+ * The size of the letterboxes to add, in pixels. Letterboxes are the
+ * horizontal black boxes added to images which are scaled down to fit the
+ * destination because they are too wide (the width is scaled to exactly
+ * fit the destination, resulting in extra space at the top and bottom).
+ *
+ * @param psize
+ * The size of the pillarboxes to add, in pixels. Pillarboxes are the
+ * vertical black boxes added to images which are scaled down to fit the
+ * destination because they are too tall (the height is scaled to exactly
+ * fit the destination, resulting in extra space on the sides).
+ *
* @return
* A pointer to a newly-allocated AVFrame containing exactly the same image
* data as the given buffer. The image data within the frame and the frame
* itself must be manually freed later.
*/
-static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer) {
+static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer, int lsize,
+ int psize) {
+
+ /* Init size of left/right pillarboxes */
+ int left = psize;
+ int right = psize;
+
+ /* Init size of top/bottom letterboxes */
+ int top = lsize;
+ int bottom = lsize;
/* Prepare source frame for buffer */
AVFrame* frame = av_frame_alloc();
@@ -275,8 +296,8 @@ static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer) {
/* Copy buffer properties to frame */
frame->format = AV_PIX_FMT_RGB32;
- frame->width = buffer->width;
- frame->height = buffer->height;
+ frame->width = buffer->width + left + right;
+ frame->height = buffer->height + top + bottom;
/* Allocate actual backing data for frame */
if (av_image_alloc(frame->data, frame->linesize, frame->width,
@@ -300,16 +321,46 @@ static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer) {
int width = buffer->width;
int height = buffer->height;
- /* Source buffer and destination frame dimensions are identical */
- assert(width == frame->width);
- assert(height == frame->height);
+ /* Source buffer is guaranteed to fit within destination buffer */
+ assert(width <= frame->width);
+ assert(height <= frame->height);
+
+ /* Add top margin */
+ while (top > 0) {
+ memset(dst_data, 0, frame->width * 4);
+ dst_data += dst_stride;
+ top--;
+ }
/* Copy all data from source buffer to destination frame */
while (height > 0) {
- memcpy(dst_data, src_data, width * 4);
+
+ /* Calculate size of margin and data regions */
+ int left_size = left * 4;
+ int data_size = width * 4;
+ int right_size = right * 4;
+
+ /* Add left margin */
+ memset(dst_data, 0, left_size);
+
+ /* Copy data */
+ memcpy(dst_data + left_size, src_data, data_size);
+
+ /* Add right margin */
+ memset(dst_data + left_size + data_size, 0, right_size);
+
dst_data += dst_stride;
src_data += src_stride;
+
height--;
+
+ }
+
+ /* Add bottom margin */
+ while (bottom > 0) {
+ memset(dst_data, 0, frame->width * 4);
+ dst_data += dst_stride;
+ bottom--;
}
/* Frame converted */
@@ -319,21 +370,45 @@ static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer) {
void guacenc_video_prepare_frame(guacenc_video* video, guacenc_buffer* buffer) {
+ int lsize;
+ int psize;
+
/* Ignore NULL buffers */
if (buffer == NULL || buffer->surface == NULL)
return;
+ /* Obtain destination frame */
+ AVFrame* dst = video->next_frame;
+
+ /* Determine width of image if height is scaled to match destination */
+ int scaled_width = buffer->width * dst->height / buffer->height;
+
+ /* Determine height of image if width is scaled to match destination */
+ int scaled_height = buffer->height * dst->width / buffer->width;
+
+ /* If height-based scaling results in a fit width, add pillarboxes */
+ if (scaled_width <= dst->width) {
+ lsize = 0;
+ psize = (dst->width - scaled_width)
+ * buffer->height / dst->height / 2;
+ }
+
+ /* If width-based scaling results in a fit width, add letterboxes */
+ else {
+ assert(scaled_height <= dst->height);
+ psize = 0;
+ lsize = (dst->height - scaled_height)
+ * buffer->width / dst->width / 2;
+ }
+
/* Prepare source frame for buffer */
- AVFrame* src = guacenc_video_frame_convert(buffer);
+ AVFrame* src = guacenc_video_frame_convert(buffer, lsize, psize);
if (src == NULL) {
guacenc_log(GUAC_LOG_WARNING, "Failed to allocate source frame. "
"Frame dropped.");
return;
}
- /* Obtain destination frame */
- AVFrame* dst = video->next_frame;
-
/* Prepare scaling context */
struct SwsContext* sws = sws_getContext(src->width, src->height,
PIX_FMT_RGB32, dst->width, dst->height, PIX_FMT_YUV420P,