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;
}
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)