From cb0e1da98eef7db293163a7196df5c87df2bf054 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 6 Apr 2023 17:30:06 +0800 Subject: [PATCH 1/1] tmp --- scf_def.h | 38 ++++++++ scf_list.h | 81 +++++++++++++++++ scf_vector.h | 198 +++++++++++++++++++++++++++++++++++++++++ simp.c | 124 ++++++++++++++++++++++++++ simp.h | 87 ++++++++++++++++++ simp_ffmpeg.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++ simp_ffmpeg.h | 22 +++++ 7 files changed, 789 insertions(+) create mode 100644 scf_def.h create mode 100644 scf_list.h create mode 100644 scf_vector.h create mode 100644 simp.c create mode 100644 simp.h create mode 100644 simp_ffmpeg.c create mode 100644 simp_ffmpeg.h diff --git a/scf_def.h b/scf_def.h new file mode 100644 index 0000000..c735f34 --- /dev/null +++ b/scf_def.h @@ -0,0 +1,38 @@ +#ifndef SCF_DEF_H +#define SCF_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 1 +#include +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 index 0000000..4b5812c --- /dev/null +++ b/scf_list.h @@ -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 index 0000000..d4249ca --- /dev/null +++ b/scf_vector.h @@ -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 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 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 index 0000000..63f6777 --- /dev/null +++ b/simp_ffmpeg.c @@ -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 index 0000000..93cfda5 --- /dev/null +++ b/simp_ffmpeg.h @@ -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 + -- 2.25.1