[FFmpeg-devel] [PATCH] avformat/tee: Move to new BSF API
sebechlebskyjan at gmail.com
sebechlebskyjan at gmail.com
Wed May 11 00:44:09 CEST 2016
From: Jan Sebechlebsky <sebechlebskyjan at gmail.com>
Signed-off-by: Jan Sebechlebsky <sebechlebskyjan at gmail.com>
---
libavformat/tee.c | 171 ++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 139 insertions(+), 32 deletions(-)
diff --git a/libavformat/tee.c b/libavformat/tee.c
index 806beaa..ff0918b 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -36,9 +36,14 @@ typedef enum {
#define DEFAULT_SLAVE_FAILURE_POLICY ON_SLAVE_FAILURE_ABORT
+typedef struct TeeBSFList {
+ AVBSFContext *bsf_ctx;
+ struct TeeBSFList *next;
+} TeeBSFList;
+
typedef struct {
AVFormatContext *avf;
- AVBitStreamFilterContext **bsfs; ///< bitstream filters per stream
+ TeeBSFList **bsfs; ///< bitstream filters per stream
SlaveFailurePolicy on_fail;
@@ -113,30 +118,61 @@ fail:
* The list must be specified in the form:
* BSFS ::= BSF[,BSFS]
*/
-static int parse_bsfs(void *log_ctx, const char *bsfs_spec,
- AVBitStreamFilterContext **bsfs)
+static int parse_bsfs(AVFormatContext *avf, const char *bsfs_spec,
+ TeeBSFList **bsfs, int stream_nr)
{
char *bsf_name, *buf, *dup, *saveptr;
int ret = 0;
+ const AVBitStreamFilter *filter;
+ AVBSFContext *bsf_ctx;
+ TeeBSFList *bsf_lst;
+ AVStream *stream = avf->streams[stream_nr];
+ AVRational last_tb = stream->time_base;
if (!(dup = buf = av_strdup(bsfs_spec)))
return AVERROR(ENOMEM);
while (bsf_name = av_strtok(buf, ",", &saveptr)) {
- AVBitStreamFilterContext *bsf = av_bitstream_filter_init(bsf_name);
+ filter = av_bsf_get_by_name(bsf_name);
+
+ if (!filter) {
+ av_log(avf, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n",
+ bsf_name);
+ ret = AVERROR(EINVAL);
+ goto end;
+ }
- if (!bsf) {
- av_log(log_ctx, AV_LOG_ERROR,
- "Cannot initialize bitstream filter with name '%s', "
- "unknown filter or internal error happened\n",
+ if ((ret = av_bsf_alloc(filter, &bsf_ctx)) < 0) {
+ av_log(avf, AV_LOG_ERROR, "Cannot initialize bitstream filter '%s'",
bsf_name);
- ret = AVERROR_UNKNOWN;
goto end;
}
- /* append bsf context to the list of bsf contexts */
- *bsfs = bsf;
- bsfs = &bsf->next;
+ ret = avcodec_parameters_copy(bsf_ctx->par_in, stream->codecpar);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ bsf_ctx->time_base_in = last_tb;
+
+ if ((ret = av_bsf_init(bsf_ctx)) < 0) {
+ goto fail;
+ }
+
+ last_tb = bsf_ctx->time_base_out;
+
+ /* allocate new bsf list node and append to the list of bsf contexts */
+ bsf_lst = av_mallocz(sizeof(TeeBSFList));
+
+ if (!bsf_lst) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ bsf_lst->bsf_ctx = bsf_ctx;
+
+ *bsfs = bsf_lst;
+ bsfs = &bsf_lst->next;
buf = NULL;
}
@@ -144,6 +180,10 @@ static int parse_bsfs(void *log_ctx, const char *bsfs_spec,
end:
av_free(dup);
return ret;
+fail:
+ av_free(dup);
+ av_bsf_free(&bsf_ctx);
+ return ret;
}
static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
@@ -163,6 +203,75 @@ static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *t
return AVERROR(EINVAL);
}
+/**
+ * Apply bitstream filters and write frame(s)
+ */
+static int tee_process_packet(AVFormatContext *avf, TeeBSFList *bsf, AVPacket *pkt,
+ AVRational pkt_tb, int stream_nr)
+{
+ int ret_all = 0,ret;
+ if (!bsf) {
+ if (pkt) {
+ AVRational out_tb = avf->streams[stream_nr]->time_base;
+ pkt->pts = av_rescale_q(pkt->pts, pkt_tb, out_tb);
+ pkt->dts = av_rescale_q(pkt->dts, pkt_tb, out_tb);
+ pkt->duration = av_rescale_q(pkt->duration, pkt_tb, out_tb);
+ pkt->stream_index = stream_nr;
+
+ ret_all = av_interleaved_write_frame(avf, pkt);
+ }
+ goto end;
+ }
+
+ if ((ret_all = av_bsf_send_packet(bsf->bsf_ctx, pkt)) < 0) {
+ return ret_all;
+ }
+
+ do {
+ if (!(ret = av_bsf_receive_packet(bsf->bsf_ctx, pkt))) {
+ ret = tee_process_packet(avf, bsf->next, pkt,
+ bsf->bsf_ctx->time_base_out, stream_nr);
+ }
+ } while(!ret);
+
+ if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
+ ret_all = ret;
+ }
+
+end:
+ return ret_all;
+}
+
+static void free_bsfs(TeeBSFList *bsf_list) {
+ TeeBSFList *next, *current = bsf_list;
+
+ while (current) {
+ av_bsf_free(¤t->bsf_ctx);
+ next = current->next;
+ av_free(current);
+ current = next;
+ }
+}
+
+static int flush_bsfs(TeeSlave *tee_slave)
+{
+ AVFormatContext *avf = tee_slave->avf;
+ int i;
+ int ret, retAll = 0;
+
+ for (i = 0; i < avf->nb_streams; i++) {
+ if (tee_slave->bsfs) {
+ ret = tee_process_packet(avf, tee_slave->bsfs[i], NULL,
+ av_make_q(1,0), i);
+ if (!retAll && ret < 0) {
+ retAll = ret;
+ }
+ }
+ }
+
+ return retAll;
+}
+
static int close_slave(TeeSlave *tee_slave)
{
AVFormatContext *avf;
@@ -173,17 +282,20 @@ static int close_slave(TeeSlave *tee_slave)
if (!avf)
return 0;
- if (tee_slave->header_written)
+ if (tee_slave->header_written) {
+ ret = flush_bsfs(tee_slave);
+ if (ret < 0) {
+ av_log(avf, AV_LOG_ERROR, "Error flushing bitstream filters: %s\n",
+ av_err2str(ret));
+ }
ret = av_write_trailer(avf);
+ }
+
+ flush_bsfs(tee_slave);
if (tee_slave->bsfs) {
for (i = 0; i < avf->nb_streams; ++i) {
- AVBitStreamFilterContext *bsf_next, *bsf = tee_slave->bsfs[i];
- while (bsf) {
- bsf_next = bsf->next;
- av_bitstream_filter_close(bsf);
- bsf = bsf_next;
- }
+ free_bsfs(tee_slave->bsfs[i]);
}
}
av_freep(&tee_slave->stream_map);
@@ -362,7 +474,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
"output '%s', filters will be ignored\n", i, filename);
continue;
}
- ret = parse_bsfs(avf, entry->value, &tee_slave->bsfs[i]);
+ ret = parse_bsfs(avf, entry->value, &tee_slave->bsfs[i], i);
if (ret < 0) {
av_log(avf, AV_LOG_ERROR,
"Error parsing bitstream filter sequence '%s' associated to "
@@ -399,7 +511,7 @@ static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
slave->avf->filename, slave->avf->oformat->name);
for (i = 0; i < slave->avf->nb_streams; i++) {
AVStream *st = slave->avf->streams[i];
- AVBitStreamFilterContext *bsf = slave->bsfs[i];
+ TeeBSFList *bsf = slave->bsfs[i];
av_log(log_ctx, log_level, " stream:%d codec:%s type:%s",
i, avcodec_get_name(st->codecpar->codec_id),
@@ -408,7 +520,7 @@ static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
av_log(log_ctx, log_level, " bsfs:");
while (bsf) {
av_log(log_ctx, log_level, "%s%s",
- bsf->filter->name, bsf->next ? "," : "");
+ bsf->bsf_ctx->filter->name, bsf->next ? "," : "");
bsf = bsf->next;
}
}
@@ -516,7 +628,7 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
int ret_all = 0, ret;
unsigned i, s;
int s2;
- AVRational tb, tb2;
+ AVRational tb;
for (i = 0; i < tee->nb_slaves; i++) {
if (!(avf2 = tee->slaves[i].avf))
@@ -533,16 +645,11 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
ret_all = ret;
continue;
}
+
tb = avf ->streams[s ]->time_base;
- tb2 = avf2->streams[s2]->time_base;
- pkt2.pts = av_rescale_q(pkt->pts, tb, tb2);
- pkt2.dts = av_rescale_q(pkt->dts, tb, tb2);
- pkt2.duration = av_rescale_q(pkt->duration, tb, tb2);
- pkt2.stream_index = s2;
-
- if ((ret = av_apply_bitstream_filters(avf2->streams[s2]->codec, &pkt2,
- tee->slaves[i].bsfs[s2])) < 0 ||
- (ret = av_interleaved_write_frame(avf2, &pkt2)) < 0) {
+
+ if ((ret = tee_process_packet(avf2, tee->slaves[i].bsfs[s2], &pkt2,
+ tb, s2)) < 0) {
ret = tee_process_slave_failure(avf, i, ret);
if (!ret_all && ret < 0)
ret_all = ret;
--
1.9.1
More information about the ffmpeg-devel
mailing list