[FFmpeg-devel] [PATCH v5 02/12] global: Merge AVSubtitle into AVFrame
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Mon Sep 13 01:05:00 EEST 2021
Soft Works:
> Signed-off-by: softworkz <softworkz at hotmail.com>
> ---
> diff --git a/libavutil/frame.c b/libavutil/frame.c
> index ef2867d318..1855de9b3d 100644
> --- a/libavutil/frame.c
> +++ b/libavutil/frame.c
> @@ -72,7 +72,12 @@ static void get_frame_defaults(AVFrame *frame)
> frame->colorspace = AVCOL_SPC_UNSPECIFIED;
> frame->color_range = AVCOL_RANGE_UNSPECIFIED;
> frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
> - frame->flags = 0;
> + frame->subtitle_start_time = 0;
> + frame->subtitle_end_time = 0;
> + frame->num_subtitle_rects = 0;
> + frame->subtitle_rects = NULL;
> + frame->subtitle_pts = 0;
> + frame->subtitle_header = NULL;
> }
>
> static void free_side_data(AVFrameSideData **ptr_sd)
> @@ -306,6 +311,9 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
> dst->colorspace = src->colorspace;
> dst->color_range = src->color_range;
> dst->chroma_location = src->chroma_location;
> + dst->subtitle_start_time = src->subtitle_start_time;
> + dst->subtitle_end_time = src->subtitle_end_time;
> + dst->subtitle_pts = src->subtitle_pts;
>
> av_dict_copy(&dst->metadata, src->metadata, 0);
>
> @@ -359,6 +367,19 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
> if (ret < 0)
> goto fail;
>
> + /* duplicate subtitle rects */
> + dst->num_subtitle_rects = src->num_subtitle_rects;
> +
> + if (src->num_subtitle_rects) {
> + dst->subtitle_rects = av_malloc_array(src->num_subtitle_rects, sizeof(AVSubtitleRect *));
> +
> + for (i = 0; i < src->num_subtitle_rects; i++) {
> + AVSubtitleRect *rect = src->subtitle_rects[i];
> + rect->nb_refs++;
> + dst->subtitle_rects[i] = rect;
> + }
> + }
> +
> /* duplicate the frame data if it's not refcounted */
> if (!src->buf[0]) {
> ret = av_frame_get_buffer2(dst, 0);
> @@ -472,6 +493,24 @@ void av_frame_unref(AVFrame *frame)
> av_buffer_unref(&frame->opaque_ref);
> av_buffer_unref(&frame->private_ref);
>
> + for (i = 0; i < frame->num_subtitle_rects; i++) {
> + AVSubtitleRect *rect = frame->subtitle_rects[i];
> +
> + if (rect && rect->nb_refs > 0)
> + rect->nb_refs--;
> + else {
> + av_freep(&rect->data[0]);
> + av_freep(&rect->data[1]);
> + av_freep(&rect->data[2]);
> + av_freep(&rect->data[3]);
> + av_freep(&rect->text);
> + av_freep(&rect->ass);
> + av_freep(&rect);
This should better be av_freep(&frame->subtitle_rects[i]);
> + }
> + }
> +
> + av_freep(&frame->subtitle_rects);
> +
> get_frame_defaults(frame);
> }
>
> diff --git a/libavutil/frame.h b/libavutil/frame.h
> index 005eed9d18..4e2cfe19b3 100644
> --- a/libavutil/frame.h
> +++ b/libavutil/frame.h
> @@ -34,6 +34,7 @@
> #include "rational.h"
> #include "samplefmt.h"
> #include "pixfmt.h"
> +#include "subfmt.h"
> #include "version.h"
>
>
> @@ -469,6 +470,17 @@ typedef struct AVFrame {
> */
> uint64_t channel_layout;
>
> + uint32_t subtitle_start_time; /* display start time, relative to packet pts, in ms */
> + uint32_t subtitle_end_time; /* display end time, relative to packet pts, in ms */
> + unsigned num_subtitle_rects;
> + AVSubtitleRect **subtitle_rects;
> + int64_t subtitle_pts; ///< Same as packet pts, in AV_TIME_BASE
> +
> + /**
> + * Header containing style information for text subtitles.
> + */
> + char *subtitle_header;
> +
> /**
> * AVBuffer references backing the data for this frame. If all elements of
> * this array are NULL, then this frame is not reference counted. This array
> diff --git a/libavutil/subfmt.c b/libavutil/subfmt.c
> new file mode 100644
> index 0000000000..9a19d01aa3
> --- /dev/null
> +++ b/libavutil/subfmt.c
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (c) 2021 softworkz
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <string.h>
> +#include "common.h"
> +#include "subfmt.h"
> +
> +typedef struct SubtitleFmtInfo {
> + enum AVSubtitleType fmt;
> + char* name;
> +} SubtitleFmtInfo;
> +
> +static SubtitleFmtInfo sub_fmt_info[AV_SUBTITLE_FMT_NB] = {
> + {.fmt = AV_SUBTITLE_FMT_UNKNOWN, .name = "Unknown subtitle format", },
> + {.fmt = AV_SUBTITLE_FMT_BITMAP, .name = "Graphical subtitles", },
> + {.fmt = AV_SUBTITLE_FMT_TEXT, .name = "Text subtitles (plain)", },
> + {.fmt = AV_SUBTITLE_FMT_ASS, .name = "Text subtitles (ass)", },
> +};
> +
> +const char *av_get_subtitle_fmt_name(enum AVSubtitleType sub_fmt)
> +{
> + if (sub_fmt < 0 || sub_fmt >= AV_SUBTITLE_FMT_NB)
> + return NULL;
> + return sub_fmt_info[sub_fmt].name;
> +}
> +
> +enum AVSubtitleType av_get_subtitle_fmt(const char *name)
> +{
> + int i;
> +
> + for (i = 0; i < AV_SUBTITLE_FMT_NB; i++)
> + if (!strcmp(sub_fmt_info[i].name, name))
> + return i;
> + return AV_SUBTITLE_FMT_NONE;
> +}
> diff --git a/libavutil/subfmt.h b/libavutil/subfmt.h
> new file mode 100644
> index 0000000000..31dabc957c
> --- /dev/null
> +++ b/libavutil/subfmt.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (c) 2021 softworkz
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef AVUTIL_SUBFMT_H
> +#define AVUTIL_SUBFMT_H
> +
> +#include <inttypes.h>
> +
> +enum AVSubtitleType {
> +
> + /**
> + * Subtitle format unknown.
> + */
> + AV_SUBTITLE_FMT_NONE = -1,
> +
> + /**
> + * Subtitle format unknown.
> + */
> + AV_SUBTITLE_FMT_UNKNOWN = 0,
> +
> + /**
> + * Bitmap area in AVSubtitleRect.data, pixfmt AV_PIX_FMT_PAL8.
> + */
> + AV_SUBTITLE_FMT_BITMAP = 1,
> +
> + /**
> + * Plain text in AVSubtitleRect.text.
> + */
> + AV_SUBTITLE_FMT_TEXT = 2,
> +
> + /**
> + * Text Formatted as per ASS specification, contained AVSubtitleRect.ass.
> + */
> + AV_SUBTITLE_FMT_ASS = 3,
> +
> + AV_SUBTITLE_FMT_NB,
> +};
> +
> +typedef struct AVSubtitleRect {
> + unsigned nb_refs;
This reference counter (which is off by one compared to an ordinary
reference counter) is nonatomic. This is unacceptable. After all, we are
in a multithreading world.
(We have certain fallback compatibility version for stdatomics; these
are nonpublic headers that are not public and can't even be made public
-- some use avpriv functions that are not part of the public API. So
don't be surprised if it is not feasible to add an atomic refcount to a
public API.)
> + int x; ///< top left corner of pict, undefined when pict is not set
> + int y; ///< top left corner of pict, undefined when pict is not set
> + int w; ///< width of pict, undefined when pict is not set
> + int h; ///< height of pict, undefined when pict is not set
> + int nb_colors; ///< number of colors in pict, undefined when pict is not set
> +
> + /**
> + * data+linesize for the bitmap of this subtitle.
> + */
> + uint8_t *data[4];
> + int linesize[4];
> +
> + enum AVSubtitleType type;
> +
> + char *text; ///< 0 terminated plain UTF-8 text
> +
> + /**
> + * 0-terminated ASS/SSA compatible event line.
> + */
> + char *ass;
> +
> + int flags;
> +} AVSubtitleRect;
> +
> +/**
> + * Return the name of sub_fmt, or NULL if sub_fmt is not
> + * recognized.
> + */
> +const char *av_get_subtitle_fmt_name(enum AVSubtitleType sub_fmt);
> +
> +/**
> + * Return a subtitle format corresponding to name, or AV_SUBTITLE_FMT_NONE
> + * on error.
> + */
> +enum AVSubtitleType av_get_subtitle_fmt(const char *name);
> +
> +#endif /* AVUTIL_SUBFMT_H */
>
More information about the ffmpeg-devel
mailing list