simp ffmpeg
authoryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 13:55:40 +0000 (21:55 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 13:55:40 +0000 (21:55 +0800)
simp.c
simp.h
simp_ffmpeg.c
simp_ffmpeg.h

diff --git a/simp.c b/simp.c
index fe368e2a4f195aa0fc46fea7186156ed52d6a9b3..ea539822bd379fe5cb559aabd5d65329510697d6 100644 (file)
--- a/simp.c
+++ b/simp.c
@@ -1,7 +1,10 @@
 #include"simp.h"
 
+extern simp_avio_ops_t   simp_avio_ffmpeg;
+
 static simp_avio_ops_t*  avio_array[] =
 {
+       &simp_avio_ffmpeg,
        NULL,
 };
 
@@ -60,6 +63,10 @@ int simp_avio_open(simp_avio_t** pio, const char* type, const char* path)
        scf_list_init(&io->vout);
        scf_list_init(&io->aout);
 
+       pthread_mutex_init(&io->mutex);
+       pthread_cond_init (&io->cond);
+
+       io->tid      = -1;
        io->width    = -1;
        io->height   = -1;
        io->channels = -1;
diff --git a/simp.h b/simp.h
index eb77bdd06df5445cef0e75866f380eb8c3e2e108..ad44575d0410997668ce8f7b36d9410a19cb2cb9 100644 (file)
--- a/simp.h
+++ b/simp.h
@@ -44,6 +44,12 @@ struct  simp_avio_s
        AVRational           sample_rate;
        int                  channels;
 
+       int                  error;
+       int                  exit;
+       pthread_t            tid;
+       pthread_mutex_t      mutex;
+       pthread_cond_t       cond;
+
        simp_avio_ops_t*     ops;
        void*                priv;
 };
index 63f6777c385b9436b9cdbaacca2e6826f84bb57b..cf31eef509b7998f70c0ea7b43dd272db2c0a042 100644 (file)
@@ -73,14 +73,22 @@ static int _ffmpeg_open(simp_avio_t* io, const char* path)
        if (!priv)
                return -ENOMEM;
 
-       pthread_mutex_init(&priv->mutex);
-       pthread_cond_init (&priv->cond);
-
-       priv->tid   = -1;
 
        priv->vidx  = -1;
        priv->aidx  = -1;
 
+       priv->vframe = av_frame_alloc();
+       if (!priv->vframe) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       priv->aframe = av_frame_alloc();
+       if (!priv->aframe) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
        ret = avformat_open_input(&priv->fmt_ctx, path, NULL, NULL);
        if (ret < 0) {
                scf_loge("ret: %s\n", av_err2str(ret));
@@ -138,6 +146,12 @@ error:
        if (priv->adec_ctx)
                avcodec_close(priv->adec_ctx);
 
+       if (priv->vframe)
+               av_frame_free(&priv->vframe);
+
+       if (priv->aframe)
+               av_frame_free(&priv->aframe);
+
        free(priv);
        return ret;
 }
@@ -147,10 +161,17 @@ static int _ffmpeg_close(simp_avio_t* io)
        simp_ffmpeg_t* priv;
 
        if (io) {
+               pthread_mutex_lock(&io->mutex);
+               io->exit = 1;
+               while (-1 != io->tid) {
+                       pthread_cond_signal(&io->cond);
+                       pthread_cond_signal(&io->cond);
+               }
+               pthread_mutex_unlock(&io->mutex);
+
                priv = io->priv;
 
                if (priv) {
-
                        if (priv->fmt_ctx)
                                avformat_close_input(&priv->fmt_ctx);
 
@@ -160,6 +181,12 @@ static int _ffmpeg_close(simp_avio_t* io)
                        if (priv->adec_ctx)
                                avcodec_close(priv->adec_ctx);
 
+                       if (priv->vframe)
+                               av_frame_free(&priv->vframe);
+
+                       if (priv->aframe)
+                               av_frame_free(&priv->aframe);
+
                        free(priv);
                }
        }
@@ -167,17 +194,54 @@ static int _ffmpeg_close(simp_avio_t* io)
        return 0;
 }
 
+int __ffmpeg_decode(simp_avio_t* io, AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, scf_list_t* h)
+{
+       int ret = avcodec_send_packet(dec_ctx, pkt);
+       if (ret < 0) {
+               scf_loge("avcodec_send_packet error, ret: %s\n", av_err2str(ret));
+               return ret;
+       }
+
+       while (ret >= 0) {
+               ret = avcodec_receive_frame(dec_ctx, frame);
+
+               if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                       break;
+               else if (ret < 0) {
+                       printf("avcodec_receive_frame error, ret: %d, %s\n", ret, av_err2str(ret));
+                       return ret;
+               }
+
+               frame->pts = frame->best_effort_timestamp;
+
+               simp_frame_t* f = simp_frame_alloc();
+               if (!f)
+                       return -ENOMEM;
+
+               ret = av_frame_copy(f->frame, frame);
+               if (ret < 0)
+                       return ret;
+
+               pthread_mutex_lock(&io->mutex);
+               scf_list_add_tail(h, &f->list);
+               pthread_cond_signal(&io->cond);
+               pthread_mutex_unlock(&io->mutex);
+       }
+
+       return 0;
+}
+
 void* __ffmpeg_run(void* arg)
 {
-       simp_avio_t*    io   = arg;
-       simp_ffmpeg_t*  priv = io->priv;
-       AVPacket*       pkt;
+       simp_avio_t*    io     = arg;
+       simp_ffmpeg_t*  priv   = io->priv;
+       AVPacket*       pkt    = NULL;
+
+       int key_frame = 0;
 
        pkt = av_packet_alloc();
        if (!pkt)
-               return NULL;
-
-       int key_frame = 0;
+               goto end;
 
        while (!priv->exit) {
 
@@ -185,6 +249,7 @@ void* __ffmpeg_run(void* arg)
                if (ret < 0) {
                        scf_loge("av_read_frame error, ret: %s\n", av_err2str(ret));
                        av_packet_free(&pkt);
+                       priv->error = ret;
                        break;
                }
 
@@ -195,6 +260,12 @@ void* __ffmpeg_run(void* arg)
                                continue;
                        }
 
+                       ret = __ffmpeg_decode(io, priv->adec_ctx, pkt, priv->aframe, &io->ain);
+                       if (ret < 0) {
+                               io->error = ret;
+                               goto end;
+                       }
+
                } else if (pkt->stream_index == priv->vidx) {
 
                        if (pkt->flags & AV_PKT_FLAG_KEY)
@@ -205,31 +276,31 @@ void* __ffmpeg_run(void* arg)
                                continue;
                        }
 
-                       ret = avcodec_send_packet(priv->vdec_ctx, pkt);
-                       av_packet_unref(&pkt);
+                       ret = __ffmpeg_decode(io, priv->vdec_ctx, pkt, priv->vframe, &io->vin);
                        if (ret < 0) {
-                               scf_loge("avcodec_send_packet error, ret: %s\n", av_err2str(ret));
-                               break;
-                       }
-
-                       while (ret >= 0) {
-                               ret = avcodec_receive_frame(priv->vdec_ctx, frame);
+                               io->error = ret;
+                               goto end;
                        }
-
-               } else {
-                       av_packet_unref(pkt);
-                       continue;
                }
+
+               av_packet_unref(&pkt);
        }
 
+end:
+       if (pkt)
+               av_packet_free(&pkt);
+
+       pthread_mutex_lock(&io->mutex);
+       io->tid = -1;
+       pthread_cond_signal(&io->cond);
+       pthread_mutex_unlock(&io->mutex);
+
        return NULL;
 }
 
 static int _ffmpeg_run(simp_avio_t* io)
 {
-       simp_ffmpeg_t* priv = io->priv;
-
-       if (pthread_create(&priv->tid, NULL, __ffmpeg_run, io)) {
+       if (pthread_create(&io->tid, NULL, __ffmpeg_run, io)) {
                scf_loge("\n");
                return -1;
        }
@@ -237,3 +308,11 @@ static int _ffmpeg_run(simp_avio_t* io)
        return 0;
 }
 
+simp_avio_ops_t  simp_avio_ffmpeg =
+{
+       .type     =  "ffmpeg_input",
+       .open     =  _ffmpeg_open,
+       .close    =  _ffmpeg_close,
+       .run      =  _ffmpeg_run,
+};
+
index 93cfda5750d1a1f83f9157d31447247ab3814588..c200b8d225651b61d3ea7770c44c55ae8f96328a 100644 (file)
@@ -11,10 +11,8 @@ typedef struct {
        int               vidx;
        int               aidx;
 
-       int               exit;
-       pthread_t         tid;
-       pthread_mutex_t   mutex;
-       pthread_cond_t    cond;
+       AVFrame*          vframe;
+       AVFrame*          aframe;
 
 } simp_ffmpeg_t;