From: yu.dongliang <18588496441@163.com> Date: Thu, 6 Apr 2023 13:55:40 +0000 (+0800) Subject: simp ffmpeg X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=f067292b5e533bf792557f857b7f33b4d06112ce;p=simplay.git simp ffmpeg --- diff --git a/simp.c b/simp.c index fe368e2..ea53982 100644 --- 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 eb77bdd..ad44575 100644 --- 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; }; diff --git a/simp_ffmpeg.c b/simp_ffmpeg.c index 63f6777..cf31eef 100644 --- a/simp_ffmpeg.c +++ b/simp_ffmpeg.c @@ -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, +}; + diff --git a/simp_ffmpeg.h b/simp_ffmpeg.h index 93cfda5..c200b8d 100644 --- a/simp_ffmpeg.h +++ b/simp_ffmpeg.h @@ -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;