Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas George <george@nsup.org>2014-12-04 15:37:08 +0300
committerMichael Niedermayer <michaelni@gmx.at>2015-01-02 22:17:05 +0300
commit55763b6f5edace9dea809a5ec11aff08276d1d72 (patch)
tree4067a31b1f3f4284fb36a938fd148a37856e76ae /libavdevice/lavfi.c
parentc6bb651bce2b17aa4e278ee8f354fd21d08952d1 (diff)
lavd/lavfi: allow to extract subcc.
Signed-off-by: Nicolas George <george@nsup.org> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavdevice/lavfi.c')
-rw-r--r--libavdevice/lavfi.c92
1 files changed, 85 insertions, 7 deletions
diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index 1398ece508..d0e6bf5f4d 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -51,7 +51,10 @@ typedef struct {
int *sink_stream_map;
int *sink_eof;
int *stream_sink_map;
+ int *sink_stream_subcc_map;
AVFrame *decoded_frame;
+ int nb_sinks;
+ AVPacket subcc_packet;
} LavfiContext;
static int *create_all_formats(int n)
@@ -82,6 +85,7 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx)
av_freep(&lavfi->sink_stream_map);
av_freep(&lavfi->sink_eof);
av_freep(&lavfi->stream_sink_map);
+ av_freep(&lavfi->sink_stream_subcc_map);
av_freep(&lavfi->sinks);
avfilter_graph_free(&lavfi->graph);
av_frame_free(&lavfi->decoded_frame);
@@ -89,6 +93,27 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx)
return 0;
}
+static int create_subcc_streams(AVFormatContext *avctx)
+{
+ LavfiContext *lavfi = avctx->priv_data;
+ AVStream *st;
+ int stream_idx, sink_idx;
+
+ for (stream_idx = 0; stream_idx < lavfi->nb_sinks; stream_idx++) {
+ sink_idx = lavfi->stream_sink_map[stream_idx];
+ if (lavfi->sink_stream_subcc_map[sink_idx]) {
+ lavfi->sink_stream_subcc_map[sink_idx] = avctx->nb_streams;
+ if (!(st = avformat_new_stream(avctx, NULL)))
+ return AVERROR(ENOMEM);
+ st->codec->codec_id = AV_CODEC_ID_EIA_608;
+ st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+ } else {
+ lavfi->sink_stream_subcc_map[sink_idx] = -1;
+ }
+ }
+ return 0;
+}
+
av_cold static int lavfi_read_header(AVFormatContext *avctx)
{
LavfiContext *lavfi = avctx->priv_data;
@@ -153,6 +178,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
/* count the outputs */
for (n = 0, inout = output_links; inout; n++, inout = inout->next);
+ lavfi->nb_sinks = n;
if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n)))
FAIL(AVERROR(ENOMEM));
@@ -160,6 +186,8 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
FAIL(AVERROR(ENOMEM));
if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n)))
FAIL(AVERROR(ENOMEM));
+ if (!(lavfi->sink_stream_subcc_map = av_malloc(sizeof(int) * n)))
+ FAIL(AVERROR(ENOMEM));
for (i = 0; i < n; i++)
lavfi->stream_sink_map[i] = -1;
@@ -167,14 +195,22 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
/* parse the output link names - they need to be of the form out0, out1, ...
* create a mapping between them and the streams */
for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
- int stream_idx;
- if (!strcmp(inout->name, "out"))
- stream_idx = 0;
- else if (sscanf(inout->name, "out%d\n", &stream_idx) != 1) {
+ int stream_idx = 0, suffix = 0, use_subcc = 0;
+ sscanf(inout->name, "out%n%d%n", &suffix, &stream_idx, &suffix);
+ if (!suffix) {
av_log(avctx, AV_LOG_ERROR,
"Invalid outpad name '%s'\n", inout->name);
FAIL(AVERROR(EINVAL));
}
+ if (inout->name[suffix]) {
+ if (!strcmp(inout->name + suffix, "+subcc")) {
+ use_subcc = 1;
+ } else {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid outpad suffix '%s'\n", inout->name);
+ FAIL(AVERROR(EINVAL));
+ }
+ }
if ((unsigned)stream_idx >= n) {
av_log(avctx, AV_LOG_ERROR,
@@ -192,6 +228,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
}
lavfi->sink_stream_map[i] = stream_idx;
lavfi->stream_sink_map[stream_idx] = i;
+ lavfi->sink_stream_subcc_map[i] = !!use_subcc;
}
/* for each open output create a corresponding stream */
@@ -203,7 +240,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
}
/* create a sink for each output and connect them to the graph */
- lavfi->sinks = av_malloc_array(avctx->nb_streams, sizeof(AVFilterContext *));
+ lavfi->sinks = av_malloc_array(lavfi->nb_sinks, sizeof(AVFilterContext *));
if (!lavfi->sinks)
FAIL(AVERROR(ENOMEM));
@@ -267,7 +304,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
}
/* fill each stream with the information in the corresponding sink */
- for (i = 0; i < avctx->nb_streams; i++) {
+ for (i = 0; i < lavfi->nb_sinks; i++) {
AVFilterLink *link = lavfi->sinks[lavfi->stream_sink_map[i]]->inputs[0];
AVStream *st = avctx->streams[i];
st->codec->codec_type = link->type;
@@ -298,6 +335,9 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
}
}
+ if ((ret = create_subcc_streams(avctx)) < 0)
+ FAIL(ret);
+
if (!(lavfi->decoded_frame = av_frame_alloc()))
FAIL(AVERROR(ENOMEM));
@@ -310,6 +350,30 @@ end:
return ret;
}
+static int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame,
+ int sink_idx)
+{
+ LavfiContext *lavfi = avctx->priv_data;
+ AVFrameSideData *sd;
+ int stream_idx, i, ret;
+
+ if ((stream_idx = lavfi->sink_stream_subcc_map[sink_idx]) < 0)
+ return 0;
+ for (i = 0; i < frame->nb_side_data; i++)
+ if (frame->side_data[i]->type == AV_FRAME_DATA_A53_CC)
+ break;
+ if (i >= frame->nb_side_data)
+ return 0;
+ sd = frame->side_data[i];
+ if ((ret = av_new_packet(&lavfi->subcc_packet, sd->size)) < 0)
+ return ret;
+ memcpy(lavfi->subcc_packet.data, sd->data, sd->size);
+ lavfi->subcc_packet.stream_index = stream_idx;
+ lavfi->subcc_packet.pts = frame->pts;
+ lavfi->subcc_packet.pos = av_frame_get_pkt_pos(frame);
+ return 0;
+}
+
static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
{
LavfiContext *lavfi = avctx->priv_data;
@@ -321,9 +385,17 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
int ret, i;
int size = 0;
+ if (lavfi->subcc_packet.size) {
+ *pkt = lavfi->subcc_packet;
+ av_init_packet(&lavfi->subcc_packet);
+ lavfi->subcc_packet.size = 0;
+ lavfi->subcc_packet.data = NULL;
+ return pkt->size;
+ }
+
/* iterate through all the graph sinks. Select the sink with the
* minimum PTS */
- for (i = 0; i < avctx->nb_streams; i++) {
+ for (i = 0; i < lavfi->nb_sinks; i++) {
AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
double d;
int ret;
@@ -397,6 +469,12 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
av_bprint_finalize(&meta_buf, NULL);
}
+ if ((ret = create_subcc_packet(avctx, frame, min_pts_sink_idx)) < 0) {
+ av_frame_unref(frame);
+ av_packet_unref(pkt);
+ return ret;
+ }
+
pkt->stream_index = stream_idx;
pkt->pts = frame->pts;
pkt->pos = av_frame_get_pkt_pos(frame);