@@ -52,7 +52,8 @@ static void tlog_ref(void *ctx, AVFrame *ref, int end)
ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
ref->pts, ref->pkt_pos);
- if (ref->width) {
+ switch(ref->type) {
+ case AVMEDIA_TYPE_VIDEO:
ff_tlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
ref->sample_aspect_ratio.num, ref->sample_aspect_ratio.den,
ref->width, ref->height,
@@ -60,12 +61,13 @@ static void tlog_ref(void *ctx, AVFrame *ref, int end)
ref->top_field_first ? 'T' : 'B', /* Top / Bottom */
ref->key_frame,
av_get_picture_type_char(ref->pict_type));
- }
- if (ref->nb_samples) {
+ break;
+ case AVMEDIA_TYPE_AUDIO:
ff_tlog(ctx, " cl:%"PRId64"d n:%d r:%d",
ref->channel_layout,
ref->nb_samples,
ref->sample_rate);
+ break;
}
ff_tlog(ctx, "]%s", end ? "\n" : "");
@@ -348,6 +350,14 @@ int avfilter_config_links(AVFilterContext *filter)
if (!link->time_base.num && !link->time_base.den)
link->time_base = (AVRational) {1, link->sample_rate};
+
+ break;
+
+ case AVMEDIA_TYPE_SUBTITLE:
+ if (!link->time_base.num && !link->time_base.den)
+ link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q;
+
+ break;
}
if (link->src->nb_inputs && link->src->inputs[0]->hw_frames_ctx &&
@@ -1013,6 +1023,10 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
av_assert1(frame->width == link->w);
av_assert1(frame->height == link->h);
}
+ } else if (link->type == AVMEDIA_TYPE_SUBTITLE) {
+ if (frame->format != link->format) {
+ av_log(link->dst, AV_LOG_WARNING, "Subtitle format change from %d to %d\n", link->format, frame->format);
+ }
} else {
if (frame->format != link->format) {
av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n");
@@ -45,6 +45,7 @@
#include "libavutil/log.h"
#include "libavutil/samplefmt.h"
#include "libavutil/pixfmt.h"
+#include "libavutil/subfmt.h"
#include "libavutil/rational.h"
#include "libavfilter/version_major.h"
@@ -349,6 +350,12 @@ typedef struct AVFilter {
* and outputs use the same sample rate and channel count/layout.
*/
const enum AVSampleFormat *samples_list;
+ /**
+ * Analogous to pixels, but delimited by AV_SUBTITLE_FMT_NONE
+ * and restricted to filters that only have AVMEDIA_TYPE_SUBTITLE
+ * inputs and outputs.
+ */
+ const enum AVSubtitleType *subs_list;
/**
* Equivalent to { pix_fmt, AV_PIX_FMT_NONE } as pixels_list.
*/
@@ -357,6 +364,10 @@ typedef struct AVFilter {
* Equivalent to { sample_fmt, AV_SAMPLE_FMT_NONE } as samples_list.
*/
enum AVSampleFormat sample_fmt;
+ /**
+ * Equivalent to { sub_fmt, AV_SUBTITLE_FMT_NONE } as subs_list.
+ */
+ enum AVSubtitleType sub_fmt;
} formats;
int priv_size; ///< size of private data to allocate for the filter
@@ -309,6 +309,8 @@ static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterForm
return ret;
break;
+ case AVMEDIA_TYPE_SUBTITLE:
+ return 0;
default:
av_assert0(!"reached");
}
@@ -439,6 +441,9 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
if (!link)
continue;
+ if (link->type == AVMEDIA_TYPE_SUBTITLE)
+ continue;
+
neg = ff_filter_get_negotiation(link);
av_assert0(neg);
for (neg_step = 1; neg_step < neg->nb_mergers; neg_step++) {
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/subfmt.h"
#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
@@ -491,6 +492,13 @@ AVFilterFormats *ff_all_formats(enum AVMediaType type)
return NULL;
fmt++;
}
+ } else if (type == AVMEDIA_TYPE_SUBTITLE) {
+ if (ff_add_format(&ret, AV_SUBTITLE_FMT_BITMAP) < 0)
+ return NULL;
+ if (ff_add_format(&ret, AV_SUBTITLE_FMT_ASS) < 0)
+ return NULL;
+ if (ff_add_format(&ret, AV_SUBTITLE_FMT_TEXT) < 0)
+ return NULL;
}
return ret;
@@ -774,6 +782,10 @@ int ff_default_query_formats(AVFilterContext *ctx)
type = AVMEDIA_TYPE_AUDIO;
formats = ff_make_format_list(f->formats.samples_list);
break;
+ case FF_FILTER_FORMATS_SUBFMTS_LIST:
+ type = AVMEDIA_TYPE_SUBTITLE;
+ formats = ff_make_format_list(f->formats.subs_list);
+ break;
case FF_FILTER_FORMATS_SINGLE_PIXFMT:
type = AVMEDIA_TYPE_VIDEO;
formats = ff_make_formats_list_singleton(f->formats.pix_fmt);
@@ -782,6 +794,10 @@ int ff_default_query_formats(AVFilterContext *ctx)
type = AVMEDIA_TYPE_AUDIO;
formats = ff_make_formats_list_singleton(f->formats.sample_fmt);
break;
+ case FF_FILTER_FORMATS_SINGLE_SUBFMT:
+ type = AVMEDIA_TYPE_SUBTITLE;
+ formats = ff_make_formats_list_singleton(f->formats.sub_fmt);
+ break;
default:
av_assert2(!"Unreachable");
/* Intended fallthrough */
@@ -183,6 +183,9 @@ av_warn_unused_result
int ff_add_channel_layout(AVFilterChannelLayouts **l,
const AVChannelLayout *channel_layout);
+av_warn_unused_result
+int ff_add_subtitle_type(AVFilterFormats **avff, int64_t fmt);
+
/**
* Add *ref as a new reference to f.
*/
@@ -148,9 +148,11 @@ static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_act
enum FilterFormatsState {
/**
- * The default value meaning that this filter supports all formats
- * and (for audio) sample rates and channel layouts/counts as long
- * as these properties agree for all inputs and outputs.
+ * The default value meaning that this filter supports
+ * - For video: all formats
+ * - For audio: all sample rates and channel layouts/counts
+ * - For subtitles: all subtitle formats
+ * as long as these properties agree for all inputs and outputs.
* This state is only allowed in case all inputs and outputs actually
* have the same type.
* The union is unused in this state.
@@ -161,8 +163,10 @@ enum FilterFormatsState {
FF_FILTER_FORMATS_QUERY_FUNC, ///< formats.query active.
FF_FILTER_FORMATS_PIXFMT_LIST, ///< formats.pixels_list active.
FF_FILTER_FORMATS_SAMPLEFMTS_LIST, ///< formats.samples_list active.
+ FF_FILTER_FORMATS_SUBFMTS_LIST, ///< formats.subs_list active.
FF_FILTER_FORMATS_SINGLE_PIXFMT, ///< formats.pix_fmt active
FF_FILTER_FORMATS_SINGLE_SAMPLEFMT, ///< formats.sample_fmt active.
+ FF_FILTER_FORMATS_SINGLE_SUBFMT, ///< formats.sub_fmt active.
};
#define FILTER_QUERY_FUNC(func) \
@@ -174,16 +178,24 @@ enum FilterFormatsState {
#define FILTER_SAMPLEFMTS_ARRAY(array) \
.formats.samples_list = array, \
.formats_state = FF_FILTER_FORMATS_SAMPLEFMTS_LIST
+#define FILTER_SUBFMTS_ARRAY(array) \
+ .formats.subs_list = array, \
+ .formats_state = FF_FILTER_FORMATS_SUBFMTS_LIST
#define FILTER_PIXFMTS(...) \
FILTER_PIXFMTS_ARRAY(((const enum AVPixelFormat []) { __VA_ARGS__, AV_PIX_FMT_NONE }))
#define FILTER_SAMPLEFMTS(...) \
FILTER_SAMPLEFMTS_ARRAY(((const enum AVSampleFormat[]) { __VA_ARGS__, AV_SAMPLE_FMT_NONE }))
+#define FILTER_SUBFMTS(...) \
+ FILTER_SUBFMTS_ARRAY(((const enum AVSubtitleType[]) { __VA_ARGS__, AV_SUBTITLE_FMT_NONE }))
#define FILTER_SINGLE_PIXFMT(pix_fmt_) \
.formats.pix_fmt = pix_fmt_, \
.formats_state = FF_FILTER_FORMATS_SINGLE_PIXFMT
#define FILTER_SINGLE_SAMPLEFMT(sample_fmt_) \
.formats.sample_fmt = sample_fmt_, \
.formats_state = FF_FILTER_FORMATS_SINGLE_SAMPLEFMT
+#define FILTER_SINGLE_SUBFMT(sub_fmt_) \
+ .formats.sub_fmt = sub_fmt_, \
+ .formats_state = FF_FILTER_FORMATS_SINGLE_SUBFMT
#define FILTER_INOUTPADS(inout, array) \
.inout = array, \