[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(&current->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