tmp
authoryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 14:54:44 +0000 (22:54 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 14:54:44 +0000 (22:54 +0800)
simp_ffmpeg_output.c [new file with mode: 0644]

diff --git a/simp_ffmpeg_output.c b/simp_ffmpeg_output.c
new file mode 100644 (file)
index 0000000..447c007
--- /dev/null
@@ -0,0 +1,268 @@
+#include"simp_ffmpeg.h"
+#include"scf_log.h"
+
+static int _video_init(simp_ffmpeg_t* priv)
+{
+       AVStream* s;
+       AVCodec*  c;
+
+       c = avcodec_find_encoder(priv->fmt_ctx->oformat->video_codec);
+       if (!c)
+               return -EINVAL;
+
+       s = avformat_new_stream(priv->fmt_ctx, c);
+       if (!s)
+               return -ENOMEM;
+
+       s->id      = priv->fmt_ctx->nb_streams - 1;
+       priv->vidx = s->id;
+
+       priv->vdec_ctx = avcodec_alloc_context3(c);
+       if (!priv->vdec_ctx)
+               return -1;
+
+       priv->vdec_ctx->codec_id     = c->codec_id;
+       priv->vdec_ctx->bit_rate     = 1024 * 1024;
+       priv->vdec_ctx->width        = 1920;
+       priv->vdec_ctx->height       = 1080;
+       priv->vdec_ctx->time_base    = (AVRational){1, 25};
+       priv->vdec_ctx->gop_size     = 20;
+       priv->vdec_ctx->max_b_frames = 2;
+       priv->vdec_ctx->pix_fmt      = AV_PIX_FMT_YUV420P;
+       s->time_base                 = priv->vdec_ctx->time_base;
+
+       if (priv->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
+               priv->vdec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
+       int ret = avcodec_open2(priv->vdec_ctx, c, NULL);
+       if (ret < 0) {
+               printf("avcodec_parameters_to_context error, ret: %d, %s\n", ret, av_err2str(ret));
+               return ret;
+       }
+
+       return 0;
+}
+
+static int _audio_init(simp_ffmpeg_t* priv)
+{
+       AVStream* s;
+       AVCodec*  c;
+
+       c = avcodec_find_encoder(priv->fmt_ctx->oformat->audio_codec);
+       if (!c)
+               return -EINVAL;
+
+       s = avformat_new_stream(priv->fmt_ctx, c);
+       if (!s)
+               return -ENOMEM;
+
+       s->id      = priv->fmt_ctx->nb_streams - 1;
+       priv->aidx = s->id;
+
+       priv->adec_ctx = avcodec_alloc_context3(c);
+       if (!priv->adec_ctx)
+               return -1;
+
+       priv->adec_ctx->codec_id       = c->codec_id;
+       priv->adec_ctx->bit_rate       = 64 * 1024;
+       priv->adec_ctx->sample_rate    = 44100;
+       priv->adec_ctx->sample_fmt     = AV_SAMPLE_FMT_FLTP;
+       priv->adec_ctx->channels       = 2;
+       priv->adec_ctx->channel_layout = av_get_default_channel_layout(priv->adec_ctx->channels);
+       priv->adec_ctx->time_base      = (AVRational){1, priv->adec_ctx->sample_rate};
+       s->time_base                   = priv->adec_ctx->time_base;
+
+       if (priv->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
+               priv->adec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
+       int ret = avcodec_open2(priv->adec_ctx, c, NULL);
+       if (ret < 0) {
+               printf("avcodec_parameters_to_context error, ret: %d, %s\n", ret, av_err2str(ret));
+               return ret;
+       }
+
+       return 0;
+}
+
+static int _ffmpeg_open(simp_avio_t* io, const char* path)
+{
+       simp_ffmpeg_t* priv;
+       AVStream*      s;
+
+       int ret;
+       int i;
+
+       priv = calloc(1, sizeof(simp_ffmpeg_t));
+       if (!priv)
+               return -ENOMEM;
+
+       priv->vidx  = -1;
+       priv->aidx  = -1;
+
+       avformat_alloc_output_context2(&priv->fmt_ctx, NULL, NULL, path);
+       if (!priv->fmt_ctx) {
+               scf_loge("\n");
+               goto error;
+       }
+
+       if (priv->fmt_ctx->oformat->video_codec != AV_CODEC_ID_NONE) {
+
+               ret = _video_init(priv);
+               if (ret < 0)
+                       goto error;
+       }
+
+       if (priv->fmt_ctx->oformat->audio_codec != AV_CODEC_ID_NONE) {
+
+               ret = _audio_init(priv);
+               if (ret < 0)
+                       goto error;
+       }
+
+
+       io->priv = priv;
+       return 0;
+
+error:
+       if (priv->fmt_ctx)
+               avformat_close_output(&priv->fmt_ctx);
+
+       if (priv->vdec_ctx)
+               avcodec_close(priv->vdec_ctx);
+
+       if (priv->adec_ctx)
+               avcodec_close(priv->adec_ctx);
+
+       free(priv);
+       return ret;
+}
+
+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_output(&priv->fmt_ctx);
+
+                       if (priv->vdec_ctx)
+                               avcodec_close(priv->vdec_ctx);
+
+                       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 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    = NULL;
+
+       simp_frame_t*   vf;
+       simp_frame_t*   af;
+       scf_list_t*     vl;
+       scf_list_t*     al;
+
+       pkt = av_packet_alloc();
+       if (!pkt)
+               goto end;
+
+       while (!priv->exit) {
+               pthread_mutex_lock(&io->mutex);
+
+               pthread_mutex_unlock(&io->mutex);
+
+
+
+       }
+
+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)
+{
+       if (pthread_create(&io->tid, NULL, __ffmpeg_run, io)) {
+               scf_loge("\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+simp_avio_ops_t  simp_avio_ffmpeg_output =
+{
+       .type     =  "ffmpeg_output",
+       .open     =  _ffmpeg_open,
+       .close    =  _ffmpeg_close,
+       .run      =  _ffmpeg_run,
+};
+