--- /dev/null
+#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,
+};
+