filter
authoryu.dongliang <18588496441@163.com>
Sat, 8 Apr 2023 14:41:22 +0000 (22:41 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 8 Apr 2023 14:41:22 +0000 (22:41 +0800)
simp.h
simp_filter.c

diff --git a/simp.h b/simp.h
index 5337255a56277951aa90ada678438cbb16d65d96..f209d878f8ff4cdafdd3813119746e2ba2a2c076 100644 (file)
--- a/simp.h
+++ b/simp.h
@@ -35,6 +35,8 @@ struct  simp_avio_s
        scf_list_t           vout;
        scf_list_t           aout;
 
+       int64_t              start_time;
+
        int                  x;
        int                  y;
        int                  width;
@@ -72,6 +74,15 @@ struct  simp_filter_s
        AVFilterGraph*       agraph;
        AVFilterContext*     abuffersink_ctx;
        AVFilterContext*     vbuffersink_ctx;
+
+       AVFrame*             vframe;
+       AVFrame*             aframe;
+
+       int                  error;
+       int                  exit;
+       pthread_t            tid;
+       pthread_mutex_t      mutex;
+       pthread_cond_t       cond;
 };
 
 struct  simp_avio_ops_s
index 9568210201fffa7055e294136f397712467972fc..ed9c19e7c633688e0a746ab4d22ddd79998a5c6e 100644 (file)
@@ -169,8 +169,26 @@ int simp_filter_open(simp_filter_t** pf)
        if (!f)
                return -ENOMEM;
 
+       f->vframe = av_frame_alloc();
+       if (!f->vframe) {
+               free(f);
+               return -ENOMEM;
+       }
+
+       f->aframe = av_frame_alloc();
+       if (!f->aframe) {
+               av_frame_free(&f->vframe);
+               free(f);
+               return -ENOMEM;
+       }
+
        scf_list_init(&f->inputs);
        scf_list_init(&f->outputs);
+
+       pthread_mutex_init(&f->mutex);
+       pthread_cond_init (&f->cond);
+
+       f->tid = -1;
        return 0;
 }
 
@@ -180,9 +198,185 @@ int simp_filter_close(simp_filter_t*  f)
        return -1;
 }
 
+static void* __filter_run(void* arg)
+{
+       simp_filter_t* f = arg;
+
+       simp_avio_t*   io;
+       simp_frame_t*  vf;
+       simp_frame_t*  af;
+       scf_list_t*    vl;
+       scf_list_t*    al;
+       scf_list_t*    l;
+
+       while (!f->exit) {
+
+               int64_t sys_time = gettime();
+               int     vn = 0;
+               int     an = 0;
+
+               for (l = scf_list_head(&f->inputs); l != scf_list_sentinel(&f->inputs); l != scf_list_next(l)) {
+                       io = scf_list_data(l, simp_avio_t, list);
+
+                       if (io->start_time == 0)
+                               io->start_time =  gettime();
+
+                       int64_t time = sys_time - io->start_time;
+
+                       if (vopen) {
+                               pthread_mutex_lock(&io->mutex);
+
+                               if (!scf_list_empty(&io->vin)) {
+
+                                       vl = scf_list_head(&io->vin);
+                                       vf = scf_list_data(vl, simp_frame_t, list);
+
+                                       int64_t vtime = vf->frame->pts * av_q2d(io->frame_rate) * 1000000LL;
+
+                                       if (vtime < time) {
+                                               scf_list_del(&vf->list);
+                                               pthread_mutex_unlock(&io->mutex);
+
+                                               int ret = av_buffersrc_add_frame_flags(io->vbuffersrc_ctx, vf->frame, AV_BUFFERSRC_FLAG_KEEP_REF);
+
+                                               simp_frame_free(vf);
+                                               vf = NULL;
+
+                                               if (ret < 0) {
+                                                       scf_loge("av_buffersrc_add_frame_flags error\n");
+                                                       f->error = -1;
+                                                       goto error;
+                                               }
+                                       } else
+                                               pthread_mutex_unlock(&io->mutex);
+
+                               } else {
+                                       pthread_cond_signal(&io->cond);
+                                       pthread_mutex_unlock(&io->mutex);
+                               }
+                       }
+
+                       if (aopen) {
+                               pthread_mutex_lock(&io->mutex);
+
+                               if (!scf_list_empty(&io->ain)) {
+
+                                       al = scf_list_head(&io->ain);
+                                       af = scf_list_data(al, simp_frame_t, list);
+
+                                       int64_t atime = af->frame->pts * av_q2d(io->sample_rate) * 1000000LL;
+
+                                       if (atime < time) {
+                                               scf_list_del(&af->list);
+                                               pthread_mutex_unlock(&io->mutex);
+
+                                               int ret = av_buffersrc_add_frame_flags(io->abuffersrc_ctx, af->frame, AV_BUFFERSRC_FLAG_KEEP_REF);
+                                               simp_frame_free(af);
+                                               af = NULL;
+
+                                               if (ret < 0) {
+                                                       scf_loge("av_buffersrc_add_frame_flags error\n");
+                                                       f->error = -1;
+                                                       goto error;
+                                               }
+                                       } else
+                                               pthread_mutex_unlock(&io->mutex);
+
+                               } else {
+                                       pthread_cond_signal(&io->cond);
+                                       pthread_mutex_unlock(&io->mutex);
+                               }
+                       }
+               }
+       }
+
+       while (1) {
+               int ret = av_buffersink_get_frame(f->vbuffersink_ctx, f->vframe);
+
+               if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+                       break;
+               } else if (ret < 0) {
+                       scf_loge("av_buffersink_get_frame error, ret: %s\n", av_err2str(ret));
+
+                       f->error = ret;
+                       goto error;
+               }
+
+               for (l = scf_list_head(&f->outputs); l != scf_list_sentinel(&f->outputs); l != scf_list_next(l)) {
+                       io = scf_list_data(l, simp_avio_t, list);
+
+                       vf = simp_frame_alloc();
+                       if (!vf) {
+                               f->error = -ENOMEM;
+                               goto error;
+                       }
+
+                       if (av_frame_copy(vf->frame, f->vframe) < 0) {
+                               simp_frame_free(vf);
+                               vf = NULL;
+
+                               f->error = -ENOMEM;
+                               goto error;
+                       }
+
+                       pthread_mutex_lock(&io->mutex);
+                       scf_list_add_tail(&io->vout, &vf->list);
+                       pthread_cond_signal(&io->cond);
+                       pthread_mutex_unlock(&io->mutex);
+                       vf = NULL;
+               }
+       }
+
+       while (1) {
+               int ret = av_buffersink_get_frame(f->abuffersink_ctx, f->aframe);
+
+               if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+                       break;
+               } else if (ret < 0) {
+                       scf_loge("av_buffersink_get_frame error, ret: %s\n", av_err2str(ret));
+
+                       f->error = ret;
+                       goto error;
+               }
+
+               for (l = scf_list_head(&f->outputs); l != scf_list_sentinel(&f->outputs); l != scf_list_next(l)) {
+                       io = scf_list_data(l, simp_avio_t, list);
+
+                       af = simp_frame_alloc();
+                       if (!af) {
+                               f->error = -ENOMEM;
+                               goto error;
+                       }
+
+                       if (av_frame_copy(af->frame, f->aframe) < 0) {
+                               simp_frame_free(af);
+                               af = NULL;
+
+                               f->error = -ENOMEM;
+                               goto error;
+                       }
+
+                       pthread_mutex_lock(&io->mutex);
+                       scf_list_add_tail(&io->aout, &af->list);
+                       pthread_cond_signal(&io->cond);
+                       pthread_mutex_unlock(&io->mutex);
+                       af = NULL;
+               }
+       }
+
+error:
+       return NULL;
+}
+
 int simp_filter_run(simp_filter_t*  f)
 {
+       if (!f)
+               return -EINVAL;
 
+       if (pthread_create(&f->tid, NULL, __filter_run, f))
+               return -EINVAL;
+
+       return 0;
 }
 
 int simp_filter_add_input(simp_filter_t* f, simp_avio_t* input)