From: yu.dongliang <18588496441@163.com> Date: Sat, 8 Apr 2023 14:41:22 +0000 (+0800) Subject: filter X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=2a57c735a2a47a1ab51387c8e7ebf0310acd62a3;p=simplay.git filter --- diff --git a/simp.h b/simp.h index 5337255..f209d87 100644 --- 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 diff --git a/simp_filter.c b/simp_filter.c index 9568210..ed9c19e 100644 --- a/simp_filter.c +++ b/simp_filter.c @@ -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)