123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- //
- // Created by 阳坤 on 2022/1/12.
- //
- #ifndef JNI_WEB_TOOLS_H
- #define JNI_WEB_TOOLS_H
- #define LOGE(format, ...) Log(format,##__VA_ARGS__);
- #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
- #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
- #include <libavcodec/avcodec.h>
- #include <libavformat/avformat.h>
- #include <libavutil/imgutils.h>
- #include <libavutil/avutil.h>
- #include <libswscale/swscale.h>
- #include <libavutil/fifo.h>
- #include <libavformat/avio.h>
- #include <libavfilter/avfilter.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <libavfilter/buffersink.h>
- #include <libavfilter/buffersrc.h>
- #include <libswresample/swresample.h>
- #include <libavutil/opt.h>
- #include "stdio.h"
- #define kCustomIoBufferSize 32 * 1024
- #define kInitialPcmBufferSize 128 * 1024
- #define kDefaultFifoSize 1 * 1024 * 1024
- #define kMaxFifoSize 16 * 1024 * 1024
- #define DEFAULT_AUDIO_SAMPLE_RATE 44100
- #define DEFAULT_AUDIO_CHANNELS 2
- #define DEFAULT_VIDEO_FPS 25
- #define DEFAULT_FORCE_PRECISION 0
- static FILE *pFile = NULL;
- static inline void print_ffmpeg_suport_codec() {
- AVCodec *codec = av_codec_next(NULL);
- char *info = (char *) malloc(40000);
- memset(info, 0, 40000);
- while (codec != NULL) {
- if (codec->decode != NULL) {
- strcat(info, "[Decode]");
- } else {
- strcat(info, "[Encode]");
- }
- switch (codec->type) {
- case AVMEDIA_TYPE_VIDEO:
- strcat(info, "[Video]");
- break;
- case AVMEDIA_TYPE_AUDIO:
- strcat(info, "[Audeo]");
- break;
- default:
- strcat(info, "[Other]");
- break;
- }
- sprintf(info, "%s %10s\n", info, codec->name);
- codec = codec->next;
- }
- puts(info);
- free(info);
- }
- static inline void split(char *str_, char delims[], long ret[], int *count) {
- int len = strlen(str_);
- char str[strlen(str_) + 1];
- for (int i = 0; i < len; i++) {
- str[i] = str_[i];
- }
- str[len] = '\0';
- char *result = NULL;
- result = strtok(str, delims);
- int index = 0;
- while (result != NULL) {
- ret[index++] = atol(result);
- result = strtok(NULL, delims);
- }
- *count = index;
- }
- static inline long getCurrentTimeMills() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
- }
- static inline void Log(const char *format, ...) {
- char szBuffer[1024] = {0};
- char szTime[1024] = {0};
- char *p = NULL;
- int prefixLength = 0;
- const char *tag = "Core";
- time_t t; //秒时间
- struct tm *local; //本地时间
- t = time(NULL); //获取目前秒时间
- local = localtime(&t); //转为本地时间,注意,该函数非线程安全,下面的例子会使用线程安全函数localtime_r
- if (1) {
- strftime(szTime, 64, "%Y-%m-%d %H:%M:%S", local); //根据需要自定义格式
- }
- prefixLength = sprintf(szBuffer, "[%s][%s][DT] ", szTime, tag);
- p = szBuffer + prefixLength;
- if (1) {
- va_list ap;
- va_start(ap, format);
- vsnprintf(p, 1024 - prefixLength, format, ap);
- va_end(ap);
- }
- printf("%s\n", szBuffer);
- }
- static int getVideoRotate(AVDictionary *metadata);
- static int
- drop_or_add_frame_countV2(int cur_fps, int fix_fps, double sync_ipts, double sync_opts, int64_t next_pkt_duration,
- AVRational st_time_base);
- static int
- drop_or_add_frame_countV2(int cur_fps, int fix_fps, double sync_ipts, double sync_opts, int64_t next_pkt_duration,
- AVRational st_time_base) {
- int nb_frames;
- double delta, delta0;
- double duration = 1.0 / ((cur_fps / 1.0) * (1.0 / fix_fps));
- duration = FFMIN(duration, 1.0 / ((fix_fps / 1.0) * (1.0 / fix_fps)));
- duration = lrintf(next_pkt_duration * av_q2d(st_time_base) / (1.0 / fix_fps));
- delta0 = sync_ipts -
- sync_opts;
- delta = delta0 + duration;
- // LOGE("sync_ipts=%f sync_opts=%f delta=%f drop_frame=%d duration=%f \n", sync_ipts, sync_opts, delta,
- // delta < -1.1, duration);
- nb_frames = 1;
- //��ʱ����� ffmpeg.c Դ��Ҫ����Щ��û���õ���!
- if (delta0 < 0 &&
- delta > 0
- ) {
- // if (delta0 < -0.6) {
- // LOGE("Past duration %f too large\n", -delta0);
- // } else
- // LOGE("Clipping frame in rate conversion by %f\n", -delta0);
- sync_ipts = sync_opts;
- duration += delta0;
- delta0 = 0;
- }
- if (delta < -1.1)
- nb_frames = 0;
- else if (delta > 1.1) {
- nb_frames = lrintf(delta);
- }
- return nb_frames;
- }
- static int getVideoRotate(AVDictionary *metadata) {
- AVDictionaryEntry *tag = NULL;
- int m_Rotate = 0;
- tag = av_dict_get(metadata, "rotate", tag, m_Rotate);
- if (tag == NULL) {
- m_Rotate = 0;
- } else {
- int angle = atoi(tag->value);
- angle %= 360;
- if (angle == 90) {
- m_Rotate = 90;
- } else if (angle == 180) {
- m_Rotate = 180;
- } else if (angle == 270) {
- m_Rotate = 270;
- } else {
- m_Rotate = 0;
- }
- }
- return m_Rotate;
- }
- static void ffmpegLogCallback(void *ptr, int level, const char *fmt, va_list vl) {
- static int printPrefix = 1;
- static int count = 0;
- static char prev[1024] = {0};
- char line[1024] = {0};
- static int is_atty;
- AVClass *avc = ptr ? *(AVClass **) ptr : NULL;
- if (level > AV_LOG_DEBUG) {
- return;
- }
- line[0] = 0;
- if (printPrefix && avc) {
- if (avc->parent_log_context_offset) {
- AVClass **parent = *(AVClass ***) (((uint8_t *) ptr) + avc->parent_log_context_offset);
- if (parent && *parent) {
- snprintf(line, sizeof(line), "[%s @ %p] ", (*parent)->item_name(parent), parent);
- }
- }
- snprintf(line + strlen(line), sizeof(line) - strlen(line), "[%s @ %p] ", avc->item_name(ptr), ptr);
- }
- vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl);
- line[strlen(line) + 1] = 0;
- LOGE("%s", line);
- }
- static int GetAACSampleRateIndex(int sampling_frequency) {
- switch (sampling_frequency) {
- case 96000:
- return 0;
- case 88200:
- return 1;
- case 64000:
- return 2;
- case 48000:
- return 3;
- case 44100:
- return 4;
- case 32000:
- return 5;
- case 24000:
- return 6;
- case 22050:
- return 7;
- case 16000:
- return 8;
- case 12000:
- return 9;
- case 11025:
- return 10;
- case 8000:
- return 11;
- case 7350:
- return 12;
- default:
- return 0;
- }
- }
- static void close_file() {
- if (pFile) {
- fclose(pFile);
- pFile = NULL;
- }
- }
- static void savaFrame(uint8_t *pFrame, int width, int height, int frame, int size, int isRgb) {
- char szFilename[1024];
- //生成文件名称
- sprintf(szFilename, "/Users/devyk/Data/Project/piaoquan/PQMedia/temp/image/frame%d.yuv", frame);
- //创建或打开文件
- if (!pFile)
- pFile = fopen(szFilename, "wb");
- if (pFile == NULL) {
- return;
- }
- if (isRgb)
- //写入头信息
- fprintf(pFile, "P6\n%d %d\n225\n", width, height);
- //写入数据
- fwrite(pFrame, 1, size, pFile);
- }
- //创建默认的帧
- static int bf_create_default_frame(enum AVMediaType type, AVCodecContext *ctx, AVFrame **frame) {
- if (frame) {
- *frame = av_frame_alloc();
- if (!(*frame = av_frame_alloc())) {
- LOGE("Could not allocate output frame\n");
- return -1;
- }
- if (type == AVMEDIA_TYPE_AUDIO){
- (*frame)->format = AV_SAMPLE_FMT_FLTP;
- (*frame)->channel_layout = AV_CH_LAYOUT_STEREO;
- (*frame)->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
- (*frame)->channels = av_get_channel_layout_nb_channels((*frame)->channel_layout);
- (*frame)->nb_samples = 1024;
- if ((av_frame_get_buffer((*frame), 1)) != 0) {
- LOGE("av_frame_get_buffer fatal��\n");
- av_frame_free(&(*frame));
- (*frame) = NULL;
- return -1;
- }
- av_samples_set_silence((*frame)->data, 0, (*frame)->nb_samples, (*frame)->channels,
- (enum AVSampleFormat) (*frame)->format);
- (*frame)->pts = (*frame)->nb_samples;
- (*frame)->pkt_pts = (*frame)->nb_samples;
- (*frame)->pkt_dts = (*frame)->nb_samples;
- (*frame)->pkt_duration = (*frame)->nb_samples;
- } else if (type == AVMEDIA_TYPE_VIDEO){
- (*frame)->format = AV_PIX_FMT_YUV420P;
- (*frame)->width = ctx->width;
- (*frame)->height = ctx->height;
- int ret = av_frame_get_buffer(*frame, 1);
- if (ret < 0) {
- LOGE("Could not allocate the video frame data\n");
- return -1;
- }
- /* 生成黑色背景 */
- /* Y */
- for (int y = 0; y < (*frame)->height; y++) {
- for (int x = 0; x < (*frame)->width; x++) {
- (*frame)->data[0][y * (*frame)->linesize[0] + x] = 0;
- }
- }
- /* Cb and Cr */
- for (int y = 0; y < (*frame)->height / 2; y++) {
- for (int x = 0; x < (*frame)->width / 2; x++) {
- (*frame)->data[1][y * (*frame)->linesize[1] + x] = 0x80;
- (*frame)->data[2][y * (*frame)->linesize[2] + x] = 0x80;
- }
- }
- }
- }
- return 0;
- }
- static int bf_frame_2_uint8_ptr(enum AVMediaType type,AVFrame *in,uint8_t**out_data,int format){
- int sampleSize = 0;
- int audioDataSize = 0;
- int offset = 0;
- int i = 0;
- int ch = 0;
- enum AVSampleFormat sampleFormat = (enum AVSampleFormat)format;
- sampleSize = av_get_bytes_per_sample(sampleFormat);
- if (sampleSize < 0) {
- LOGE("Failed to calculate data size.");
- return -1;
- }
- audioDataSize = in->nb_samples * in->channels * sampleSize;
- int size = av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO),
- in->nb_samples,
- sampleFormat, 0);
- *out_data = (uint8_t *) av_mallocz(audioDataSize);
- if (!(*out_data))return -1;
- if (av_sample_fmt_is_planar(sampleFormat)) {//如果是平面的
- for (i = 0; i < in->nb_samples; i++) {
- for (ch = 0; ch < in->channels; ch++) {
- memcpy((*out_data) + offset, in->data[ch] + sampleSize * i, sampleSize);
- offset += sampleSize;
- }
- }
- } else {
- memcpy(*out_data, in->data[0], audioDataSize);
- }
- return audioDataSize;
- }
- #endif //JNI_WEB_TOOLS_H
|