sleep(1);
        }
 
-       simp_filter_close(f);
+       simp_filter_close(f, 1);
 
        printf("main quit ok\n");
        return 0;
 
                if (io->ops && io->ops->close)
                        io->ops->close(io);
 
+               scf_list_clear(&io->vin,  simp_frame_t, list, simp_frame_free);
+               scf_list_clear(&io->ain,  simp_frame_t, list, simp_frame_free);
+               scf_list_clear(&io->vout, simp_frame_t, list, simp_frame_free);
+               scf_list_clear(&io->aout, simp_frame_t, list, simp_frame_free);
+
                free(io);
        }
        return 0;
 
 
        int                  error;
        int                  exit;
+       int                  flush;
        pthread_t            tid;
        pthread_mutex_t      mutex;
        pthread_cond_t       cond;
 int simp_avio_stop        (simp_avio_t*    io);
 
 int simp_filter_open      (simp_filter_t** pf);
-int simp_filter_close     (simp_filter_t*  f);
+int simp_filter_close     (simp_filter_t*  f, int flush);
 int simp_filter_run       (simp_filter_t*  f);
 
 int simp_filter_add_input (simp_filter_t*  f, simp_avio_t* input);
 
                        if (priv->aframe)
                                av_frame_free(&priv->aframe);
 
+                       if (priv->vpkt)
+                               av_packet_free(&priv->vpkt);
+
+                       if (priv->apkt)
+                               av_packet_free(&priv->apkt);
+
                        free(priv);
                }
        }
                ret = avio_open(&priv->fmt_ctx->pb, priv->fmt_ctx->url, AVIO_FLAG_WRITE);
                if (ret < 0) {
                        scf_loge("Could not open output file '%s'", priv->fmt_ctx->url);
+                       io->error = ret;
                        goto end;
                }
        }
        ret = avformat_write_header(priv->fmt_ctx, NULL);
        if (ret < 0) {
                scf_loge("avformat_write_header error, ret: %s\n", av_err2str(ret));
+               io->error = ret;
                goto end;
        }
 
        }
 
 
-       if (io->flush) {
-               pthread_mutex_lock(&io->mutex);
-               while(!scf_list_empty(&io->vout)) {
-                       l = scf_list_head(&io->vout);
-                       f = scf_list_data(l, simp_frame_t, list);
-
-                       scf_list_del(&f->list);
+       pthread_mutex_lock(&io->mutex);
+       while(!scf_list_empty(&io->vout)) {
+               l = scf_list_head(&io->vout);
+               f = scf_list_data(l, simp_frame_t, list);
 
-                       scf_logd("priv->vidx: %d, frame->pts: %ld\n", priv->vidx, f->frame->pts);
+               scf_list_del(&f->list);
 
-                       if (0 == io->error) {
+               scf_logd("priv->vidx: %d, frame->pts: %ld\n", priv->vidx, f->frame->pts);
 
-                               ret = __ffmpeg_encode(io, priv->vcodec_ctx, priv->vpkt, f->frame, priv->vidx);
-                               if (ret < 0)
-                                       scf_loge("ret: %d, frame->pts: %ld\n", ret, f->frame->pts);
+               if (0 == io->error && io->flush) {
 
-                               io->error = ret;
-                       }
+                       ret = __ffmpeg_encode(io, priv->vcodec_ctx, priv->vpkt, f->frame, priv->vidx);
+                       if (ret < 0)
+                               scf_loge("ret: %d, frame->pts: %ld\n", ret, f->frame->pts);
 
-                       simp_frame_free(f);
-                       f = NULL;
+                       io->error = ret;
                }
 
-               while (!scf_list_empty(&io->aout)) {
-                       l = scf_list_head(&io->aout);
-                       f = scf_list_data(l, simp_frame_t, list);
+               simp_frame_free(f);
+               f = NULL;
+       }
 
-                       scf_list_del(&f->list);
+       while (!scf_list_empty(&io->aout)) {
+               l = scf_list_head(&io->aout);
+               f = scf_list_data(l, simp_frame_t, list);
 
-                       if (0 == io->error) {
-                               ret = av_audio_fifo_write(priv->afifo, (void**)f->frame->data, f->frame->nb_samples);
-                               if (ret < 0)
-                                       scf_loge("ret: %d\n", ret);
+               scf_list_del(&f->list);
 
-                               io->error = ret;
-                       }
+               if (0 == io->error && io->flush) {
 
-                       simp_frame_free(f);
-                       f = NULL;
+                       ret = av_audio_fifo_write(priv->afifo, (void**)f->frame->data, f->frame->nb_samples);
+                       if (ret < 0)
+                               scf_loge("ret: %d\n", ret);
+
+                       io->error = ret;
                }
 
-               while (av_audio_fifo_size(priv->afifo) > 0) {
+               simp_frame_free(f);
+               f = NULL;
+       }
 
-                       if (0 == io->error) {
-                               ret = av_audio_fifo_read(priv->afifo, (void**)priv->aframe->data, 1024);
-                               if (ret < 0) {
-                                       scf_loge("ret: %d\n", ret);
-                                       io->error = ret;
-                                       break;
-                               }
+       while (av_audio_fifo_size(priv->afifo) > 0) {
 
-                               priv->nb_samples         += priv->aframe->nb_samples;
-                               priv->aframe->pts         = priv->nb_samples;
+               if (0 == io->error && io->flush) {
 
-                               scf_logd("aframe->pts: %ld\n", priv->aframe->pts);
+                       ret = av_audio_fifo_read(priv->afifo, (void**)priv->aframe->data, 1024);
+                       if (ret < 0) {
+                               scf_loge("ret: %d\n", ret);
+                               io->error = ret;
+                               break;
+                       }
 
-                               ret = __ffmpeg_encode(io, priv->acodec_ctx, priv->apkt, priv->aframe, priv->aidx);
-                               if (ret < 0) {
-                                       scf_loge("ret: %d\n", ret);
-                                       io->error = ret;
-                                       break;
-                               }
+                       priv->nb_samples         += priv->aframe->nb_samples;
+                       priv->aframe->pts         = priv->nb_samples;
+
+                       scf_logd("aframe->pts: %ld\n", priv->aframe->pts);
+
+                       ret = __ffmpeg_encode(io, priv->acodec_ctx, priv->apkt, priv->aframe, priv->aidx);
+                       if (ret < 0) {
+                               scf_loge("ret: %d\n", ret);
+                               io->error = ret;
+                               break;
                        }
                }
-               pthread_mutex_unlock(&io->mutex);
        }
+       pthread_mutex_unlock(&io->mutex);
 
 end:
+       ret = av_write_trailer(priv->fmt_ctx);
+       if (ret < 0) {
+               io->error = ret;
+               scf_loge("av_write_trailer error, ret: %s\n", av_err2str(ret));
+       }
+
        pthread_mutex_lock(&io->mutex);
        io->tid = -1;
        pthread_cond_signal(&io->cond);
 
        return 0;
 }
 
-int simp_filter_close(simp_filter_t*  f)
+int simp_filter_close(simp_filter_t*  f, int flush)
 {
-       scf_loge("\n");
-       return -1;
+       simp_avio_t* io;
+       scf_list_t*  l;
+
+       if (!f)
+               return -EINVAL;
+
+       pthread_mutex_lock(&f->mutex);
+       if (flush)
+               f->flush = 1;
+       else
+               f->exit = 1;
+
+       while (-1 != f->tid) {
+               pthread_cond_signal(&f->cond);
+               pthread_cond_wait(&f->cond, &f->mutex);
+       }
+       pthread_mutex_unlock(&f->mutex);
+
+       avfilter_graph_free(&f->vgraph);
+       avfilter_graph_free(&f->agraph);
+
+       f->abuffersink_ctx = NULL;
+       f->vbuffersink_ctx = NULL;
+
+       av_frame_free(&f->vframe);
+       av_frame_free(&f->aframe);
+
+       for (l = scf_list_head(&f->inputs); l != scf_list_sentinel(&f->inputs); ) {
+               io = scf_list_data(l, simp_avio_t, list);
+               l  = scf_list_next(l);
+
+               scf_list_del(&io->list);
+
+               io->abuffersrc_ctx = NULL;
+               io->vbuffersrc_ctx = NULL;
+
+               simp_avio_close(io);
+               io = NULL;
+       }
+
+       for (l = scf_list_head(&f->outputs); l != scf_list_sentinel(&f->outputs); ) {
+               io = scf_list_data(l, simp_avio_t, list);
+               l  = scf_list_next(l);
+
+               scf_list_del(&io->list);
+               simp_avio_close(io);
+               io = NULL;
+       }
+
+       return 0;
 }
 
 static int  _filter_add_video(simp_avio_t* io)
                goto error;
        }
 
+       int flushed = 0;
+
        while (!f->exit) {
-               int vn = 0;
-               int an = 0;
 
                usleep(500 * 1000);
 
                        if (io->start_time == 0)
                                io->start_time =  gettime();
 
+                       if (f->flush)
+                               simp_avio_stop(io);
+
                        if (io->vopen) {
                                f->error = _filter_add_video(io);
                                if (f->error < 0)
                                        goto error;
+
+                               if (f->flush) {
+                                       flushed++;
+
+                                       pthread_mutex_lock(&io->mutex);
+                                       if (scf_list_empty(&io->vin))
+                                               flushed--;
+                                       pthread_mutex_unlock(&io->mutex);
+                               }
                        }
 
                        if (io->aopen) {
                                f->error = _filter_add_audio(io);
                                if (f->error < 0)
                                        goto error;
+
+                               if (f->flush) {
+                                       flushed++;
+
+                                       pthread_mutex_lock(&io->mutex);
+                                       if (scf_list_empty(&io->ain))
+                                               flushed--;
+                                       pthread_mutex_unlock(&io->mutex);
+                               }
                        }
                }
 
+               if (f->flush && 0 == flushed)
+                       f->exit = 1;
+
                while (1) {
                        int ret = av_buffersink_get_frame(f->vbuffersink_ctx, f->vframe);
 
                        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 = calloc(1, sizeof(simp_frame_t));
-                               if (!vf) {
-                                       f->error = -ENOMEM;
-                                       goto error;
-                               }
+                               if (io->vopen) {
+                                       vf = calloc(1, sizeof(simp_frame_t));
+                                       if (!vf) {
+                                               f->error = -ENOMEM;
+                                               goto error;
+                                       }
 
-                               vf->frame = av_frame_clone(f->vframe);
-                               if (!vf->frame) {
-                                       simp_frame_free(vf);
-                                       vf = NULL;
+                                       vf->frame = av_frame_clone(f->vframe);
+                                       if (!vf->frame) {
+                                               simp_frame_free(vf);
+                                               vf = NULL;
 
-                                       f->error = -ENOMEM;
-                                       goto error;
-                               }
+                                               f->error = -ENOMEM;
+                                               goto error;
+                                       }
 
-                               scf_logd("vf->frame->pts: %ld\n", vf->frame->pts);
+                                       scf_logd("vf->frame->pts: %ld\n", vf->frame->pts);
 
-                               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;
+                                       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;
+                               }
                        }
 
                        av_frame_unref(f->vframe);
                        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 = calloc(1, sizeof(simp_frame_t));
-                               if (!af) {
-                                       f->error = -ENOMEM;
-                                       goto error;
-                               }
+                               if (io->aopen) {
+                                       af = calloc(1, sizeof(simp_frame_t));
+                                       if (!af) {
+                                               f->error = -ENOMEM;
+                                               goto error;
+                                       }
 
-                               af->frame = av_frame_clone(f->aframe);
-                               if (!af->frame) {
-                                       simp_frame_free(af);
-                                       af = NULL;
+                                       af->frame = av_frame_clone(f->aframe);
+                                       if (!af->frame) {
+                                               simp_frame_free(af);
+                                               af = NULL;
 
-                                       f->error = -ENOMEM;
-                                       goto error;
-                               }
+                                               f->error = -ENOMEM;
+                                               goto error;
+                                       }
+
+                                       scf_logd("af->frame->pts: %ld\n", af->frame->pts);
 
-                               scf_logd("af->frame->pts: %ld\n", af->frame->pts);
+                                       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;
+                               }
 
-                               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;
+                               if (f->flush)
+                                       io->flush = 1;
                        }
 
                        av_frame_unref(f->aframe);
        }
 
 error:
+       pthread_mutex_lock(&f->mutex);
+       f->tid = -1;
+       pthread_cond_signal(&f->cond);
+       pthread_mutex_unlock(&f->mutex);
        return NULL;
 }