tmp
authoryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 09:30:06 +0000 (17:30 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 6 Apr 2023 09:30:06 +0000 (17:30 +0800)
scf_def.h [new file with mode: 0644]
scf_list.h [new file with mode: 0644]
scf_vector.h [new file with mode: 0644]
simp.c [new file with mode: 0644]
simp.h [new file with mode: 0644]
simp_ffmpeg.c [new file with mode: 0644]
simp_ffmpeg.h [new file with mode: 0644]

diff --git a/scf_def.h b/scf_def.h
new file mode 100644 (file)
index 0000000..c735f34
--- /dev/null
+++ b/scf_def.h
@@ -0,0 +1,38 @@
+#ifndef SCF_DEF_H
+#define SCF_DEF_H
+
+#include<stdio.h>
+#include<stdint.h>
+#include<stdlib.h>
+#include<stddef.h>
+#include<string.h>
+#include<assert.h>
+#include<errno.h>
+#include<time.h>
+#include<unistd.h>
+#include<pthread.h>
+
+#if 1
+#include<sys/time.h>
+static inline int64_t gettime()
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+
+       return tv.tv_sec * 1000000LL + tv.tv_usec;
+}
+#endif
+
+#ifdef SCF_DEBUG
+#define scf_logd(fmt, ...) printf("%s(), %d, "fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define scf_logd(fmt, ...)
+#endif
+
+#define scf_logi(fmt, ...) printf("%s(), %d, info: "fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+#define scf_loge(fmt, ...) printf("%s(), %d, \033[31m error:\033[0m "fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define scf_logw(fmt, ...) printf("%s(), %d, \033[33m warning:\033[0m "fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+#endif
+
diff --git a/scf_list.h b/scf_list.h
new file mode 100644 (file)
index 0000000..4b5812c
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef SCF_LIST_H
+#define SCF_LIST_H
+
+#include"scf_def.h"
+
+typedef struct scf_list_s      scf_list_t;
+
+struct scf_list_s {
+       struct scf_list_s*              prev;
+       struct scf_list_s*              next;
+};
+
+static inline void scf_list_init(scf_list_t* h)
+{
+       h->prev = h;
+       h->next = h;
+}
+
+static inline void scf_list_del(scf_list_t* n)
+{
+       n->prev->next = n->next;
+       n->next->prev = n->prev;
+
+       // only to avoid some wrong operations for these 2 invalid pointers
+       n->prev = NULL;
+       n->next = NULL;
+}
+
+static inline void scf_list_add_tail(scf_list_t* h, scf_list_t* n)
+{
+       h->prev->next = n;
+       n->prev = h->prev;
+       n->next = h;
+       h->prev = n;
+}
+
+static inline void scf_list_add_front(scf_list_t* h, scf_list_t* n)
+{
+       h->next->prev = n;
+       n->next = h->next;
+       n->prev = h;
+       h->next = n;
+}
+
+#define SCF_LIST_INIT(h)       {&h, &h}
+
+#define scf_list_data(l, type, member) ((type*)((char*)l - offsetof(type, member)))
+
+#define scf_list_head(h)               ((h)->next)
+#define scf_list_tail(h)               ((h)->prev)
+#define scf_list_sentinel(h)   (h)
+#define scf_list_next(l)               ((l)->next)
+#define scf_list_prev(l)               ((l)->prev)
+#define scf_list_empty(h)              ((h)->next == (h))
+
+#define scf_list_clear(h, type, member, type_free) \
+       do {\
+               scf_list_t* l;\
+               for (l = scf_list_head(h); l != scf_list_sentinel(h);) {\
+                       type* t = scf_list_data(l, type, member);\
+                       l = scf_list_next(l);\
+                       scf_list_del(&t->member);\
+                       type_free(t);\
+                       t = NULL;\
+               }\
+       } while(0)
+
+#define scf_list_mov(dst, src, type, member) \
+       do {\
+               scf_list_t* l;\
+               type*       t;\
+               for (l = scf_list_head(src); l != scf_list_sentinel(src);) {\
+                       t  = scf_list_data(l, type, member);\
+                       l  = scf_list_next(l);\
+                       scf_list_del(&t->member);\
+                       scf_list_add_tail(dst, &t->member);\
+               }\
+       } while(0)
+
+#endif
+
diff --git a/scf_vector.h b/scf_vector.h
new file mode 100644 (file)
index 0000000..d4249ca
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef SCF_VECTOR_H
+#define SCF_VECTOR_H
+
+#include"scf_def.h"
+
+typedef struct {
+       int             capacity;
+       int             size;
+       void**  data;
+} scf_vector_t;
+
+#undef  NB_MEMBER_INC
+#define NB_MEMBER_INC  16
+
+static inline scf_vector_t* scf_vector_alloc()
+{
+       scf_vector_t* v = calloc(1, sizeof(scf_vector_t));
+       if (!v)
+               return NULL;
+
+       v->data = calloc(NB_MEMBER_INC, sizeof(void*));
+       if (!v->data) {
+               free(v);
+               v = NULL;
+               return NULL;
+       }
+
+       v->capacity = NB_MEMBER_INC;
+       return v;
+}
+
+static inline scf_vector_t* scf_vector_clone(scf_vector_t* origin)
+{
+       scf_vector_t* clone = calloc(1, sizeof(scf_vector_t));
+       if (!clone)
+               return NULL;
+
+       clone->data = calloc(origin->capacity, sizeof(void*));
+       if (!clone->data) {
+               free(clone);
+               clone = NULL;
+               return NULL;
+       }
+
+       clone->capacity = origin->capacity;
+       clone->size             = origin->size;
+       memcpy(clone->data, origin->data, origin->size * sizeof(void*));
+       return clone;
+}
+
+static inline int scf_vector_cat(scf_vector_t* dst, scf_vector_t* src)
+{
+       if (!dst || !src)
+               return -EINVAL;
+
+       int size = dst->size + src->size;
+       if (size > dst->capacity) {
+
+               void* p = realloc(dst->data, sizeof(void*) * (size + NB_MEMBER_INC));
+               if (!p)
+                       return -ENOMEM;
+
+               dst->data = p;
+               dst->capacity = size + NB_MEMBER_INC;
+       }
+
+       memcpy(dst->data + dst->size * sizeof(void*), src->data, src->size * sizeof(void*));
+       dst->size += src->size;
+       return 0;
+}
+
+static inline int scf_vector_add(scf_vector_t* v, void* node)
+{
+       if (!v || !v->data)
+               return -EINVAL;
+
+       assert(v->size <= v->capacity);
+
+       if (v->size == v->capacity) {
+               void* p = realloc(v->data, sizeof(void*) * (v->capacity + NB_MEMBER_INC));
+               if (!p)
+                       return -ENOMEM;
+
+               v->data = p;
+               v->capacity += NB_MEMBER_INC;
+       }
+
+       v->data[v->size++] = node;
+       return 0;
+}
+
+static inline int scf_vector_del(scf_vector_t* v, void* node)
+{
+       if (!v || !v->data)
+               return -EINVAL;
+
+       assert(v->size <= v->capacity);
+
+       int i;
+       for (i = 0; i < v->size; i++) {
+
+               if (v->data[i] != node)
+                       continue;
+
+               int j;
+               for (j = i + 1; j < v->size; j++)
+                       v->data[j - 1] = v->data[j];
+
+               v->size--;
+
+               if (v->size + NB_MEMBER_INC * 2 < v->capacity) {
+                       void* p = realloc(v->data, sizeof(void*) * (v->capacity - NB_MEMBER_INC));
+                       if (p) {
+                               v->data = p;
+                               v->capacity -= NB_MEMBER_INC;
+                       }
+               }
+               return 0;
+       }
+
+       return -1;
+}
+
+static inline void* scf_vector_find(const scf_vector_t* v, const void* node)
+{
+       int i;
+       for (i = 0; i < v->size; i++) {
+               if (node == v->data[i])
+                       return v->data[i];
+       }
+       return NULL;
+}
+
+static inline int scf_vector_add_unique(scf_vector_t* v, void* node)
+{
+       if (!scf_vector_find(v, node))
+               return scf_vector_add(v, node);
+       return 0;
+}
+
+static inline void* scf_vector_find_cmp(const scf_vector_t* v, const void* node, int (*cmp)(const void*, const void*))
+{
+       int i;
+       for (i = 0; i < v->size; i++) {
+               if (0 == cmp(node, v->data[i]))
+                       return v->data[i];
+       }
+       return NULL;
+}
+
+static inline int scf_vector_qsort(const scf_vector_t* v, int (*cmp)(const void*, const void*))
+{
+       if (!v || !v->data || 0 == v->size || !cmp)
+               return -EINVAL;
+
+       qsort(v->data, v->size, sizeof(void*), cmp);
+       return 0;
+}
+
+static inline void scf_vector_clear(scf_vector_t* v, void (*type_free)(void*))
+{
+       if (!v || !v->data)
+               return;
+
+       if (type_free) {
+               int i;
+               for (i = 0; i < v->size; i++) {
+                       if (v->data[i]) {
+                               type_free(v->data[i]);
+                               v->data[i] = NULL;
+                       }
+               }
+       }
+
+       v->size = 0;
+
+       if (v->capacity > NB_MEMBER_INC) {
+               void* p = realloc(v->data, sizeof(void*) * NB_MEMBER_INC);
+               if (p) {
+                       v->data = p;
+                       v->capacity = NB_MEMBER_INC;
+               }
+       }
+}
+
+static inline void scf_vector_free(scf_vector_t* v)
+{
+       if (v) {
+               if (v->data)
+                       free(v->data);
+
+               free(v);
+               v = NULL;
+       }
+}
+
+#endif
+
diff --git a/simp.c b/simp.c
new file mode 100644 (file)
index 0000000..fe368e2
--- /dev/null
+++ b/simp.c
@@ -0,0 +1,124 @@
+#include"simp.h"
+
+static simp_avio_ops_t*  avio_array[] =
+{
+       NULL,
+};
+
+simp_frame_t* simp_frame_alloc()
+{
+       simp_frame_t* f = malloc(sizeof(simp_frame_t));
+       if (!f)
+               return NULL;
+
+       f->frame = av_frame_alloc();
+       if (!f->frame) {
+               free(f);
+               return NULL;
+       }
+
+       return f;
+}
+
+void simp_frame_free (simp_frame_t* f)
+{
+       if (f) {
+               if (f->frame)
+                       av_frame_free(&f->frame);
+
+               free(f);
+       }
+}
+
+int simp_avio_open(simp_avio_t** pio, const char* type, const char* path)
+{
+       if (!pio || !type || !path)
+               return -EINVAL;
+
+       simp_avio_ops_t* ops = NULL;
+       simp_avio_t*     io  = NULL;
+
+       int i;
+       for (i = 0; avio_array[i]; i++) {
+
+               if (!strcmp(avio_array[i]->type, type)) {
+                       ops =   avio_array[i];
+                       break;
+               }
+       }
+
+       if (!ops)
+               return -EINVAL;
+
+       io = calloc(1, sizeof(simp_avio_t));
+       if (!io)
+               return -ENOMEM;
+
+       scf_list_init(&io->list);
+       scf_list_init(&io->vin);
+       scf_list_init(&io->ain);
+       scf_list_init(&io->vout);
+       scf_list_init(&io->aout);
+
+       io->width    = -1;
+       io->height   = -1;
+       io->channels = -1;
+
+       io->ops = ops;
+       if (ops->open) {
+
+               int ret = ops->open(io, path);
+               if (ret < 0) {
+                       free(io);
+                       return ret;
+               }
+       }
+
+       *pio = io;
+       return 0;
+}
+
+int simp_avio_close(simp_avio_t* io)
+{
+       if (io) {
+               if (io->ops && io->ops->close)
+                       io->ops->close(io);
+
+               free(io);
+       }
+       return 0;
+}
+
+int simp_avio_run(simp_avio_t* io)
+{
+       if (io && io->ops && io->ops->run)
+               return io->ops->run(io);
+
+       return -EINVAL;
+}
+
+int simp_filter_open(simp_filter_t** pf)
+{
+
+}
+
+int simp_filter_close(simp_filter_t* f)
+{
+
+}
+
+int simp_filter_run(simp_filter_t* f)
+{
+
+}
+
+int simp_filter_add_input (simp_filter_t* f, simp_avio_t* input)
+{
+
+}
+
+int simp_filter_add_output(simp_filter_t* f, simp_avio_t* output)
+{
+
+}
+
diff --git a/simp.h b/simp.h
new file mode 100644 (file)
index 0000000..eb77bdd
--- /dev/null
+++ b/simp.h
@@ -0,0 +1,87 @@
+#ifndef SIMP_H
+#define SIMP_H
+
+#include"scf_list.h"
+
+#include "libavformat/avformat.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/avutil.h"
+#include "libavutil/opt.h"
+#include "libavfilter/avfilter.h"
+#include "libavfilter/buffersrc.h"
+#include "libavfilter/buffersink.h"
+
+typedef struct simp_avio_s       simp_avio_t;
+typedef struct simp_avio_ops_s   simp_avio_ops_t;
+
+typedef struct simp_frame_s      simp_frame_t;
+
+typedef struct simp_filter_s     simp_filter_t;
+
+
+struct simp_frame_s
+{
+       scf_list_t           list;
+       AVFrame*             frame;
+};
+
+struct  simp_avio_s
+{
+       scf_list_t           list;
+
+       scf_list_t           vin;
+       scf_list_t           ain;
+
+       scf_list_t           vout;
+       scf_list_t           aout;
+
+       int                  width;
+       int                  height;
+       enum AVPixelFormat   pix_fmt;
+       AVRational           frame_rate;
+
+       enum AVSampleFormat  sample_fmt;
+       AVRational           sample_rate;
+       int                  channels;
+
+       simp_avio_ops_t*     ops;
+       void*                priv;
+};
+
+struct  simp_filter_s
+{
+       scf_list_t           inputs;
+       scf_list_t           outputs;
+
+       AVFilterGraph*       graph;
+       AVFilterContext*     abuffersrc;
+       AVFilterContext*     abuffersink;
+       AVFilterContext*     vbuffersrc;
+       AVFilterContext*     vbuffersink;
+};
+
+struct  simp_avio_ops_s
+{
+       const char*          type;
+
+       int                (*open )(simp_avio_t* io, const char* path);
+       int                (*close)(simp_avio_t* io);
+       int                (*run  )(simp_avio_t* io);
+};
+
+simp_frame_t*  simp_frame_alloc();
+void           simp_frame_free (simp_frame_t* f);
+
+int simp_avio_open        (simp_avio_t**   pio, const char* type, const char* path);
+int simp_avio_close       (simp_avio_t*    io);
+int simp_avio_run         (simp_avio_t*    io);
+
+int simp_filter_open      (simp_filter_t** pf);
+int simp_filter_close     (simp_filter_t*  f);
+int simp_filter_run       (simp_filter_t*  f);
+
+int simp_filter_add_input (simp_filter_t*  f, simp_avio_t* input);
+int simp_filter_add_output(simp_filter_t*  f, simp_avio_t* output);
+
+#endif
+
diff --git a/simp_ffmpeg.c b/simp_ffmpeg.c
new file mode 100644 (file)
index 0000000..63f6777
--- /dev/null
@@ -0,0 +1,239 @@
+#include"simp_ffmpeg.h"
+#include"scf_log.h"
+
+static int _video_init(simp_ffmpeg_t* priv)
+{
+       AVStream* s;
+       AVCodec*  c;
+
+       s = priv->fmt_ctx->streams[priv->vidx];
+
+       c = avcodec_find_decoder(s->codecpar->codec_id);
+       if (!c) {
+               scf_loge("decoder not found, codec_id: %d\n", s->codecpar->codec_id);
+               return -1;
+       }
+
+       priv->vdec_ctx = avcodec_alloc_context3(c);
+       if (!priv->vdec_ctx)
+               return -1;
+
+       int ret = avcodec_parameters_to_context(priv->vdec_ctx, s->codecpar);
+       if (ret < 0)
+               return -1;
+
+       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 -1;
+       }
+
+       return 0;
+}
+
+static int _audio_init(simp_ffmpeg_t* priv)
+{
+       AVStream* s;
+       AVCodec*  c;
+
+       s = priv->fmt_ctx->streams[priv->aidx];
+
+       c = avcodec_find_decoder(s->codecpar->codec_id);
+       if (!c) {
+               scf_loge("decoder not found, codec_id: %d\n", s->codecpar->codec_id);
+               return -1;
+       }
+
+       priv->adec_ctx = avcodec_alloc_context3(c);
+       if (!priv->adec_ctx)
+               return -1;
+
+       int ret = avcodec_parameters_to_context(priv->adec_ctx, s->codecpar);
+       if (ret < 0)
+               return -1;
+
+       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 -1;
+       }
+
+       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;
+
+       pthread_mutex_init(&priv->mutex);
+       pthread_cond_init (&priv->cond);
+
+       priv->tid   = -1;
+
+       priv->vidx  = -1;
+       priv->aidx  = -1;
+
+       ret = avformat_open_input(&priv->fmt_ctx, path, NULL, NULL);
+       if (ret < 0) {
+               scf_loge("ret: %s\n", av_err2str(ret));
+               goto error;
+       }
+
+       ret = avformat_find_stream_info(priv->fmt_ctx, NULL);
+       if (ret < 0) {
+               scf_loge("avformat_find_stream_info error, ret: %s\n", av_err2str(ret));
+               goto error;
+       }
+
+       for (i = 0; i < priv->fmt_ctx->nb_streams; i++) {
+               s  =        priv->fmt_ctx->streams[i];
+
+               if (AVMEDIA_TYPE_VIDEO == s->codecpar->codec_type)
+                       priv->vidx = i;
+
+               else if (AVMEDIA_TYPE_AUDIO == s->codecpar->codec_type)
+                       priv->aidx = i;
+
+               if (-1 != priv->vidx && -1 != priv->aidx)
+                       break;
+       }
+
+       if (-1 == priv->vidx && -1 == priv->aidx) {
+               scf_loge("no stream found\n");
+
+               ret = -1;
+               goto error;
+       }
+
+       if (priv->vidx >= 0) {
+               ret = _video_init(priv);
+               if (ret < 0)
+                       goto error;
+       }
+
+       if (priv->aidx >= 0) {
+               ret = _audio_init(priv);
+               if (ret < 0)
+                       goto error;
+       }
+
+       io->priv = priv;
+       return 0;
+
+error:
+       if (priv->fmt_ctx)
+               avformat_close_input(&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) {
+               priv = io->priv;
+
+               if (priv) {
+
+                       if (priv->fmt_ctx)
+                               avformat_close_input(&priv->fmt_ctx);
+
+                       if (priv->vdec_ctx)
+                               avcodec_close(priv->vdec_ctx);
+
+                       if (priv->adec_ctx)
+                               avcodec_close(priv->adec_ctx);
+
+                       free(priv);
+               }
+       }
+
+       return 0;
+}
+
+void* __ffmpeg_run(void* arg)
+{
+       simp_avio_t*    io   = arg;
+       simp_ffmpeg_t*  priv = io->priv;
+       AVPacket*       pkt;
+
+       pkt = av_packet_alloc();
+       if (!pkt)
+               return NULL;
+
+       int key_frame = 0;
+
+       while (!priv->exit) {
+
+               int ret = av_read_frame(priv->fmt_ctx, pkt);
+               if (ret < 0) {
+                       scf_loge("av_read_frame error, ret: %s\n", av_err2str(ret));
+                       av_packet_free(&pkt);
+                       break;
+               }
+
+               if (pkt->stream_index == priv->aidx) {
+
+                       if (0 == key_frame) {
+                               av_packet_unref(pkt);
+                               continue;
+                       }
+
+               } else if (pkt->stream_index == priv->vidx) {
+
+                       if (pkt->flags & AV_PKT_FLAG_KEY)
+                               key_frame++;
+
+                       if (0 == key_frame) {
+                               av_packet_unref(pkt);
+                               continue;
+                       }
+
+                       ret = avcodec_send_packet(priv->vdec_ctx, pkt);
+                       av_packet_unref(&pkt);
+                       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);
+                       }
+
+               } else {
+                       av_packet_unref(pkt);
+                       continue;
+               }
+       }
+
+       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)) {
+               scf_loge("\n");
+               return -1;
+       }
+
+       return 0;
+}
+
diff --git a/simp_ffmpeg.h b/simp_ffmpeg.h
new file mode 100644 (file)
index 0000000..93cfda5
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef SIMP_FFMPEG_H
+#define SIMP_FFMPEG_H
+
+#include"simp.h"
+
+typedef struct {
+       AVFormatContext*  fmt_ctx;
+       AVCodecContext*   vdec_ctx;
+       AVCodecContext*   adec_ctx;
+
+       int               vidx;
+       int               aidx;
+
+       int               exit;
+       pthread_t         tid;
+       pthread_mutex_t   mutex;
+       pthread_cond_t    cond;
+
+} simp_ffmpeg_t;
+
+#endif
+