1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#define AL_LOG_SECTION "ff_scaler"
#include <al/log.h>
#include <al/lib.h>
#include <libavutil/imgutils.h>
#include "scaler.h"
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, s32 width, s32 height)
{
AVFrame *frame = av_frame_alloc();
if (!frame) return NULL;
s32 ret = av_image_alloc(frame->data, frame->linesize, width, height, pix_fmt, 32);
if (ret < 0) {
log_error("Failed to allocate picture buffer (%s).", av_err2str(ret));
return NULL;
}
/*
s32 size = av_image_get_buffer_size(pix_fmt, width, height, 1);
u8 *buffer = (u8 *)av_malloc(size);
if (!buffer) {
av_free(frame);
return NULL;
}
s32 ret = av_image_fill_arrays(frame->data, frame->linesize, buffer, pix_fmt, width, height, 1);
if (ret < 0) {
log_error("Failed to allocate picture buffer (%s).", av_err2str(ret));
av_free(frame);
return NULL;
}
*/
frame->width = width;
frame->height = height;
frame->format = pix_fmt;
return frame;
}
static bool ff_scaler_init(struct camu_scaler *scale, struct camu_scaler_format *fmt)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)scale;
al_assert(fmt->scaler_needed);
av->fmt = *fmt;
av->scaler_context = sws_getContext(
fmt->in.width, fmt->in.height, (enum AVPixelFormat)fmt->in.format,
fmt->req.width, fmt->req.height, (enum AVPixelFormat)fmt->req.format,
SWS_BITEXACT, NULL, NULL, NULL);
if (!av->scaler_context) {
log_error("Failed to create scaler context.");
return false;
}
struct camu_codec_frame *frame = &av->frame;
frame->av.frame = alloc_picture((enum AVPixelFormat)fmt->req.format, fmt->req.width, fmt->req.height);
if (!frame->av.frame) {
log_error("Failed to allocate frame.");
return false;
}
return true;
}
static bool ff_scaler_scale(struct camu_scaler *scale, const u8 **in_slice, s32 *in_strides)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)scale;
AVFrame *frame = av->frame.av.frame;
struct camu_scaler_format *fmt = &av->fmt;
s32 slice_height = (s32)fmt->in.height;
s32 ret = sws_scale(av->scaler_context, in_slice, in_strides, 0,
slice_height, frame->data, frame->linesize);
if (ret != (s32)fmt->req.height) {
log_error("Failed to scale frame (%s).", av_err2str(ret));
return false;
}
return true;
}
static struct camu_codec_frame *ff_scaler_get_frame(struct camu_scaler *scale)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)scale;
return &av->frame;
}
static void ff_scaler_free(struct camu_scaler **scale)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)*scale;
struct camu_codec_frame *frame = &av->frame;
if (frame->av.frame) {
av_freep(&frame->av.frame->data[0]);
av_frame_free(&frame->av.frame);
}
if (av->scaler_context) {
sws_freeContext(av->scaler_context);
av->scaler_context = NULL;
}
al_free(av);
*scale = NULL;
}
struct camu_scaler *camu_ff_scaler_create(void)
{
struct camu_ff_scaler *av = al_alloc_object(struct camu_ff_scaler);
av->scale.init = ff_scaler_init;
av->scale.scale = ff_scaler_scale;
av->scale.get_frame = ff_scaler_get_frame;
av->scale.free = ff_scaler_free;
return (struct camu_scaler *)av;
}
|