free memory
authoryu.dongliang <18588496441@163.com>
Tue, 11 Apr 2023 13:41:15 +0000 (21:41 +0800)
committeryu.dongliang <18588496441@163.com>
Tue, 11 Apr 2023 13:41:15 +0000 (21:41 +0800)
main.c
simp.c
simp.h
simp_ffmpeg_output.c
simp_filter.c

diff --git a/main.c b/main.c
index f498219e0f2915c9680f26e852cb5fa8fd111c82..a7d1d8e3dc9a9ac7794d04633c78b575c1cc395e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -55,7 +55,7 @@ int main(int argc, char* argv[])
                sleep(1);
        }
 
-       simp_filter_close(f);
+       simp_filter_close(f, 1);
 
        printf("main quit ok\n");
        return 0;
diff --git a/simp.c b/simp.c
index e114bfe57824fa794b7563c309289dc8ddd99b5b..ca33005c6de2621cb7402f6e21d6da955f665d7d 100644 (file)
--- a/simp.c
+++ b/simp.c
@@ -93,6 +93,11 @@ int simp_avio_close(simp_avio_t* io)
                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;
diff --git a/simp.h b/simp.h
index 6aa2bfa485bbffbda2efd73f522813c6ee2550e0..3ced822a4b08cb3ae796051e7cd8d40e72f8f110 100644 (file)
--- a/simp.h
+++ b/simp.h
@@ -83,6 +83,7 @@ struct  simp_filter_s
 
        int                  error;
        int                  exit;
+       int                  flush;
        pthread_t            tid;
        pthread_mutex_t      mutex;
        pthread_cond_t       cond;
@@ -107,7 +108,7 @@ int simp_avio_run         (simp_avio_t*    io);
 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);
index 549226d1cc1a249e41ecca6fed8ebe58c5368a6b..db36f5c6eef1ccc8cec337d448ee69e1b74f7cb6 100644 (file)
@@ -230,6 +230,12 @@ static int _ffmpeg_output_close(simp_avio_t* io)
                        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);
                }
        }
@@ -299,6 +305,7 @@ static void* __ffmpeg_output_run(void* arg)
                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;
                }
        }
@@ -306,6 +313,7 @@ static void* __ffmpeg_output_run(void* arg)
        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;
        }
 
@@ -381,74 +389,80 @@ static void* __ffmpeg_output_run(void* arg)
        }
 
 
-       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);
index 6501430f23e88f6ee59f99b9d35cbb34bf47c303..f857ddea491c51b795bc14a9dc80034fe5994bc6 100644 (file)
@@ -205,10 +205,58 @@ int simp_filter_open(simp_filter_t** pf)
        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)
@@ -305,9 +353,9 @@ static void* __filter_run(void* arg)
                goto error;
        }
 
+       int flushed = 0;
+
        while (!f->exit) {
-               int vn = 0;
-               int an = 0;
 
                usleep(500 * 1000);
 
@@ -317,19 +365,43 @@ static void* __filter_run(void* arg)
                        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);
 
@@ -361,28 +433,30 @@ static void* __filter_run(void* arg)
                        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);
@@ -403,28 +477,33 @@ static void* __filter_run(void* arg)
                        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);
@@ -432,6 +511,10 @@ static void* __filter_run(void* arg)
        }
 
 error:
+       pthread_mutex_lock(&f->mutex);
+       f->tid = -1;
+       pthread_cond_signal(&f->cond);
+       pthread_mutex_unlock(&f->mutex);
        return NULL;
 }