|
@@ -18,11 +18,15 @@
|
|
|
#include "../util/bmem.h"
|
|
|
#include "video-scaler.h"
|
|
|
|
|
|
+#include <libavutil/imgutils.h>
|
|
|
#include <libswscale/swscale.h>
|
|
|
|
|
|
struct video_scaler {
|
|
|
struct SwsContext *swscale;
|
|
|
int src_height;
|
|
|
+ int dst_height;
|
|
|
+ uint8_t *dst_pointers[4];
|
|
|
+ int dst_linesizes[4];
|
|
|
};
|
|
|
|
|
|
static inline enum AVPixelFormat
|
|
@@ -138,6 +142,15 @@ int video_scaler_create(video_scaler_t **scaler_out,
|
|
|
|
|
|
scaler = bzalloc(sizeof(struct video_scaler));
|
|
|
scaler->src_height = src->height;
|
|
|
+ scaler->dst_height = dst->height;
|
|
|
+
|
|
|
+ ret = av_image_alloc(scaler->dst_pointers, scaler->dst_linesizes,
|
|
|
+ dst->width, dst->height, format_dst, 32);
|
|
|
+ if (ret < 0) {
|
|
|
+ blog(LOG_WARNING,
|
|
|
+ "video_scaler_create: av_image_alloc failed: %d", ret);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
|
|
|
scaler->swscale = sws_getCachedContext(NULL, src->width, src->height,
|
|
|
format_src, dst->width,
|
|
@@ -169,6 +182,10 @@ void video_scaler_destroy(video_scaler_t *scaler)
|
|
|
{
|
|
|
if (scaler) {
|
|
|
sws_freeContext(scaler->swscale);
|
|
|
+
|
|
|
+ if (scaler->dst_pointers[0])
|
|
|
+ av_freep(scaler->dst_pointers);
|
|
|
+
|
|
|
bfree(scaler);
|
|
|
}
|
|
|
}
|
|
@@ -182,13 +199,37 @@ bool video_scaler_scale(video_scaler_t *scaler, uint8_t *output[],
|
|
|
return false;
|
|
|
|
|
|
int ret = sws_scale(scaler->swscale, input, (const int *)in_linesize, 0,
|
|
|
- scaler->src_height, output,
|
|
|
- (const int *)out_linesize);
|
|
|
+ scaler->src_height, scaler->dst_pointers,
|
|
|
+ scaler->dst_linesizes);
|
|
|
if (ret <= 0) {
|
|
|
blog(LOG_ERROR, "video_scaler_scale: sws_scale failed: %d",
|
|
|
ret);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ const size_t height = scaler->dst_height;
|
|
|
+ for (size_t plane = 0; plane < 4; ++plane) {
|
|
|
+ if (!scaler->dst_pointers[plane])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ const size_t scaled_linesize = scaler->dst_linesizes[plane];
|
|
|
+ const size_t plane_linesize = out_linesize[plane];
|
|
|
+ uint8_t *dst = output[plane];
|
|
|
+ const uint8_t *src = scaler->dst_pointers[plane];
|
|
|
+ if (scaled_linesize == plane_linesize) {
|
|
|
+ memcpy(dst, src, scaled_linesize * height);
|
|
|
+ } else {
|
|
|
+ size_t linesize = scaled_linesize;
|
|
|
+ if (linesize > plane_linesize)
|
|
|
+ linesize = plane_linesize;
|
|
|
+
|
|
|
+ for (size_t y = 0; y < height; y++) {
|
|
|
+ memcpy(dst, src, linesize);
|
|
|
+ dst += plane_linesize;
|
|
|
+ src += scaled_linesize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return true;
|
|
|
}
|