swscale: explicitly track if a context is "legacy" or not

The legacy API is defined by sws_init_context(), sws_scale() etc., whereas
the "modern" API is defined by just using sws_scale_frame() without prior
init call.

This int allows us to cleanly distinguish the type of context, paving the
way for some minor refactoring.

As an immediate benefit, we now gain a bunch of explict error checks to
ensure the API is used correctly (i.e. sws_scale() not called before
sws_init_context()).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-02-26 18:46:04 +01:00
parent 5d3ad4f06e
commit 47f89ea88b
3 changed files with 21 additions and 2 deletions

View File

@@ -1208,6 +1208,8 @@ static int scale_internal(SwsContext *sws,
void sws_frame_end(SwsContext *sws)
{
SwsInternal *c = sws_internal(sws);
if (!c->is_legacy_init)
return;
av_frame_unref(c->frame_src);
av_frame_unref(c->frame_dst);
c->src_ranges.nb_ranges = 0;
@@ -1217,6 +1219,8 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
{
SwsInternal *c = sws_internal(sws);
int ret, allocated = 0;
if (!c->is_legacy_init)
return AVERROR(EINVAL);
ret = av_frame_ref(c->frame_src, src);
if (ret < 0)
@@ -1249,6 +1253,8 @@ int sws_send_slice(SwsContext *sws, unsigned int slice_start,
{
SwsInternal *c = sws_internal(sws);
int ret;
if (!c->is_legacy_init)
return AVERROR(EINVAL);
ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
if (ret < 0)
@@ -1272,6 +1278,8 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start,
SwsInternal *c = sws_internal(sws);
unsigned int align = sws_receive_slice_alignment(sws);
uint8_t *dst[4];
if (!c->is_legacy_init)
return AVERROR(EINVAL);
/* wait until complete input has been received */
if (!(c->src_ranges.nb_ranges == 1 &&
@@ -1345,9 +1353,9 @@ int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
if (!src || !dst)
return AVERROR(EINVAL);
if (c->frame_src) {
if (c->is_legacy_init) {
/* Context has been initialized with explicit values, fall back to
* legacy API */
* legacy API behavior. */
ret = sws_frame_start(sws, dst, src);
if (ret < 0)
return ret;
@@ -1516,6 +1524,9 @@ int attribute_align_arg sws_scale(SwsContext *sws,
const int dstStride[])
{
SwsInternal *c = sws_internal(sws);
if (!c->is_legacy_init)
return AVERROR(EINVAL);
if (c->nb_slice_ctx) {
sws = c->slice_ctx[0];
c = sws_internal(sws);

View File

@@ -697,6 +697,8 @@ struct SwsInternal {
// Hardware specific private data
void *hw_priv; /* refstruct */
int is_legacy_init;
};
//FIXME check init (where 0)

View File

@@ -1885,6 +1885,7 @@ av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter,
enum AVPixelFormat src_format, dst_format;
int ret;
c->is_legacy_init = 1;
c->frame_src = av_frame_alloc();
c->frame_dst = av_frame_alloc();
if (!c->frame_src || !c->frame_dst)
@@ -2254,6 +2255,11 @@ void sws_freeContext(SwsContext *sws)
for (i = 0; i < FF_ARRAY_ELEMS(c->graph); i++)
ff_sws_graph_free(&c->graph[i]);
if (!c->is_legacy_init) {
av_free(c);
return;
}
for (i = 0; i < c->nb_slice_ctx; i++)
sws_freeContext(c->slice_ctx[i]);
av_freep(&c->slice_ctx);