| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- //
- #include "ffmpeg_init.h"
- #if !NDEBUG
- #define OPEN_FFMPEG_LOG 1
- #else
- #define OPEN_FFMPEG_LOG 0
- #endif
- #define PRINT_LIB_INFO(libname, LIBNAME) \
- if (true) \
- { \
- const char* indent = " "; \
- unsigned int version = libname##_version(); \
- qInfo("%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d", indent, #libname, \
- LIB##LIBNAME##_VERSION_MAJOR, LIB##LIBNAME##_VERSION_MINOR, \
- LIB##LIBNAME##_VERSION_MICRO, AV_VERSION_MAJOR(version), \
- AV_VERSION_MINOR(version), AV_VERSION_MICRO(version)); \
- }
- #define BUFF_MAXLEN 256
- static void log_callback(void* ptr, int level, const char* fmt, va_list vl)
- {
- if (level > av_log_get_level())
- return;
- va_list vl2;
- char line[1024];
- static int print_prefix = 1;
- va_copy(vl2, vl);
- av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
- va_end(vl2);
- #if OPEN_FFMPEG_LOG
- qInfo("FFMPEG:%s", line);
- #endif
- }
- int ffmpeg_init()
- {
- av_log_set_flags(AV_LOG_SKIP_REPEATED);
- av_log_set_level(AV_LOG_INFO);
- av_log_set_callback(log_callback);
- // print_ffmpeg_info(AV_LOG_INFO);
- check_error(-22);
- return 0;
- }
- void check_error(int error)
- {
- char errorStr[256] = {0};
- qDebug("ENOMEM: %d", AVERROR(ENOMEM));
- qDebug("ENOMEM: %d", AVERROR(EINVAL));
- qDebug("ENOMEM: %d", AVERROR_OPTION_NOT_FOUND);
- av_strerror(error, errorStr, sizeof(errorStr));
- }
- void print_ffmpeg_info()
- {
- // ffmpeg-snapshot_0401
- qInfo("%s version %s", "ffmpeg", FFMPEG_VERSION);
- PRINT_LIB_INFO(avutil, AVUTIL);
- PRINT_LIB_INFO(avcodec, AVCODEC);
- PRINT_LIB_INFO(avformat, AVFORMAT);
- // PRINT_LIB_INFO(avdevice, AVDEVICE);
- // PRINT_LIB_INFO(avfilter, AVFILTER);
- PRINT_LIB_INFO(swscale, SWSCALE);
- PRINT_LIB_INFO(swresample, SWRESAMPLE);
- qInfo("");
- }
- QString dump_format(AVFormatContext* ic, int index, const char* url, int is_output)
- {
- QString str;
- char tmp[BUFF_MAXLEN];
- const char* indent = " ";
- uint8_t* printed = nullptr;
- if (!ic)
- {
- qErrnoWarning("invalid parameter!");
- goto fail;
- }
- if (!url || !url[0])
- {
- qErrnoWarning("url is invalid!");
- goto fail;
- }
- printed = ic->nb_streams ? (uint8_t*)av_mallocz(ic->nb_streams) : nullptr;
- if (ic->nb_streams && !printed)
- goto fail;
- snprintf(tmp, sizeof(tmp), "%s #%d, %s, %s '%s':",
- is_output ? "Output" : "Input", index,
- is_output ? ic->oformat->name : ic->iformat->name,
- is_output ? "to" : "from", url);
- str += tmp;
- str += "\n";
- str += dump_metadata(ic->metadata, indent);
- if (!is_output)
- {
- snprintf(tmp, sizeof(tmp), "%sDuration: ", indent);
- str += tmp;
- if (ic->duration != AV_NOPTS_VALUE)
- {
- int64_t hours, mins, secs, us;
- int64_t duration =
- ic->duration + (ic->duration <= INT64_MAX - 5000 ? 5000 : 0);
- secs = duration / AV_TIME_BASE;
- us = duration % AV_TIME_BASE;
- mins = secs / 60;
- secs %= 60;
- hours = mins / 60;
- mins %= 60;
- snprintf(tmp, sizeof(tmp), "%02lld:%02lld:%02lld.%02lld", hours, mins,
- secs, (100 * us) / AV_TIME_BASE);
- str += tmp;
- }
- else
- {
- str += "N/A";
- }
- if (ic->start_time != AV_NOPTS_VALUE)
- {
- int secs, us;
- secs = llabs(ic->start_time / AV_TIME_BASE);
- us = llabs(ic->start_time % AV_TIME_BASE);
- // av_log(nullptr, AV_LOG_INFO, ", start: %s%d.%06d",
- // ic->start_time >= 0 ? "" : "-", secs, (int)av_rescale(us, 1000000,
- // AV_TIME_BASE));
- snprintf(tmp, sizeof(tmp), ", start: %s%d.%06d",
- ic->start_time >= 0 ? "" : "-", secs,
- (int)av_rescale(us, 1000000, AV_TIME_BASE));
- str += tmp;
- }
- str += ", bitrate: ";
- if (ic->bit_rate)
- {
- snprintf(tmp, sizeof(tmp), "%lld kb/s", ic->bit_rate / 1000);
- str += tmp;
- }
- else
- str += "N/A";
- str += "\n";
- }
- if (ic->nb_chapters)
- {
- snprintf(tmp, sizeof(tmp), "%sChapters:\n", indent);
- str += tmp;
- }
- for (unsigned int i = 0; i < ic->nb_chapters; i++)
- {
- const AVChapter* ch = ic->chapters[i];
- snprintf(tmp, sizeof(tmp), " Chapter #%d:%d: start %f, end %f\n", index,
- i, ch->start * av_q2d(ch->time_base),
- ch->end * av_q2d(ch->time_base));
- str += tmp;
- str += dump_metadata(ch->metadata, " ");
- }
- if (ic->nb_programs)
- {
- unsigned int j, k, total = 0;
- for (j = 0; j < ic->nb_programs; j++)
- {
- const AVProgram* program = ic->programs[j];
- const AVDictionaryEntry* name =
- av_dict_get(program->metadata, "name", nullptr, 0);
- snprintf(tmp, sizeof(tmp), " Program %d %s\n", program->id,
- name ? name->value : "");
- str += tmp;
- str += dump_metadata(program->metadata, " ");
- for (k = 0; k < program->nb_stream_indexes; k++)
- {
- str +=
- dump_stream_format(ic, program->stream_index[k], index, is_output);
- printed[program->stream_index[k]] = 1;
- }
- total += program->nb_stream_indexes;
- }
- if (total < ic->nb_streams)
- {
- str += " No Program\n";
- }
- }
- str += "\n";
- for (unsigned int i = 0; i < ic->nb_streams; i++)
- {
- if (!printed[i])
- {
- str += dump_stream_format(ic, i, index, is_output);
- str += "\n";
- }
- }
- return str;
- fail:
- return QString("");
- }
- QString dump_metadata(const AVDictionary* m, const char* indent)
- {
- QString str;
- char tmp[BUFF_MAXLEN];
- if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", nullptr, 0)))
- {
- const AVDictionaryEntry* tag = nullptr;
- snprintf(tmp, sizeof(tmp), "%sMetadata:\n", indent);
- str += tmp;
- while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)))
- {
- if (strcmp("language", tag->key))
- {
- const char* p = tag->value;
- // av_log(ctx, AV_LOG_INFO,"%s %-16s: ", indent, tag->key);
- snprintf(tmp, sizeof(tmp), "%s %-16s: ", indent, tag->key);
- str += tmp;
- while (*p)
- {
- char tmp_str[256];
- size_t len = strcspn(p, "\x8\xa\xb\xc\xd");
- av_strlcpy(tmp_str, p, FFMIN(sizeof(tmp_str), len + 1));
- // str += "%s", tmp);
- snprintf(tmp, sizeof(tmp), "%s", tmp_str);
- str += tmp;
- p += len;
- if (*p == 0xd)
- str += " ";
- if (*p == 0xa)
- str += "\n%s %-16s: ";
- if (*p)
- p++;
- }
- str += "\n";
- }
- }
- }
- return str;
- }
- QString dump_stream_format(const AVFormatContext* ic, int i, int index, int is_output)
- {
- QString str;
- char tmp[BUFF_MAXLEN];
- char buf[256];
- int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
- const AVStream* st = ic->streams[i];
- // const FFStream* const sti = cffstream(st);
- const AVDictionaryEntry* lang =
- av_dict_get(st->metadata, "language", nullptr, 0);
- const char* separator = (const char*)ic->dump_separator;
- AVCodecContext* avctx;
- // AVCodecContext* st_avctx = (AVCodecContext*)st->priv_data;
- int ret;
- avctx = avcodec_alloc_context3(nullptr);
- if (!avctx)
- goto fail;
- ret = avcodec_parameters_to_context(avctx, st->codecpar);
- if (ret < 0)
- {
- avcodec_free_context(&avctx);
- goto fail;
- }
- // Fields which are missing from AVCodecParameters need to be taken from the
- // AVCodecContext
- /*
- avctx->properties = st_avctx->properties;
- avctx->codec = st_avctx->codec;
- avctx->qmin = st_avctx->qmin;
- avctx->qmax = st_avctx->qmax;
- avctx->coded_width = st_avctx->coded_width;
- avctx->coded_height = st_avctx->coded_height;
- if (separator)
- av_opt_set(avctx, "dump_separator", separator, 0);*/
- avcodec_string(buf, sizeof(buf), avctx, is_output);
- avcodec_free_context(&avctx);
- snprintf(tmp, sizeof(tmp), " Stream #%d:%d", index, i);
- str += tmp;
- if (flags & AVFMT_SHOW_IDS)
- {
- snprintf(tmp, sizeof(tmp), "[0x%x]", st->id);
- str += tmp;
- }
- if (lang)
- {
- snprintf(tmp, sizeof(tmp), "(%s)", lang->value);
- str += tmp;
- }
- snprintf(tmp, sizeof(tmp), ": %s", buf);
- str += tmp;
- if (st->sample_aspect_ratio.num &&
- av_cmp_q(st->sample_aspect_ratio, st->codecpar->sample_aspect_ratio))
- {
- AVRational display_aspect_ratio;
- av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
- st->codecpar->width * (int64_t)st->sample_aspect_ratio.num,
- st->codecpar->height * (int64_t)st->sample_aspect_ratio.den,
- 1024 * 1024);
- snprintf(tmp, sizeof(tmp), ", SAR %d:%d DAR %d:%d",
- st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
- display_aspect_ratio.num, display_aspect_ratio.den);
- str += tmp;
- }
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
- {
- int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
- int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
- int tbn = st->time_base.den && st->time_base.num;
- if (fps || tbr || tbn)
- {
- snprintf(tmp, sizeof(tmp), "%s", separator);
- str += tmp;
- }
- if (fps)
- str +=
- print_fps(av_q2d(st->avg_frame_rate), tbr || tbn ? "fps, " : "fps");
- if (tbr)
- str += print_fps(av_q2d(st->r_frame_rate), tbn ? "tbr, " : "tbr");
- if (tbn)
- str += print_fps(1 / av_q2d(st->time_base), "tbn");
- }
- if (st->disposition & AV_DISPOSITION_DEFAULT)
- str += " (default)";
- if (st->disposition & AV_DISPOSITION_DUB)
- str += " (dub)";
- if (st->disposition & AV_DISPOSITION_ORIGINAL)
- str += " (original)";
- if (st->disposition & AV_DISPOSITION_COMMENT)
- str += " (comment)";
- if (st->disposition & AV_DISPOSITION_LYRICS)
- str += " (lyrics)";
- if (st->disposition & AV_DISPOSITION_KARAOKE)
- str += " (karaoke)";
- if (st->disposition & AV_DISPOSITION_FORCED)
- str += " (forced)";
- if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
- str += " (hearing impaired)";
- if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
- str += " (visual impaired)";
- if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
- str += " (clean effects)";
- if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
- str += " (attached pic)";
- if (st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS)
- str += " (timed thumbnails)";
- if (st->disposition & AV_DISPOSITION_CAPTIONS)
- str += " (captions)";
- if (st->disposition & AV_DISPOSITION_DESCRIPTIONS)
- str += " (descriptions)";
- if (st->disposition & AV_DISPOSITION_METADATA)
- str += " (metadata)";
- if (st->disposition & AV_DISPOSITION_DEPENDENT)
- str += " (dependent)";
- if (st->disposition & AV_DISPOSITION_STILL_IMAGE)
- str += " (still image)";
- str += "\n";
- str += dump_metadata(st->metadata, " ");
- str += dump_sidedata(st, " ");
- return str;
- fail:
- return QString("");
- }
- QString print_fps(double d, const char* postfix)
- {
- char tmp[BUFF_MAXLEN];
- uint64_t v = lrintf(d * 100);
- if (!v)
- {
- snprintf(tmp, sizeof(tmp), "%1.4f %s", d, postfix);
- }
- else if (v % 100)
- {
- snprintf(tmp, sizeof(tmp), "%3.2f %s", d, postfix);
- }
- else if (v % (100 * 1000))
- {
- snprintf(tmp, sizeof(tmp), "%1.0f %s", d, postfix);
- }
- else
- {
- snprintf(tmp, sizeof(tmp), "%1.0fk %s", d / 1000, postfix);
- }
- return QString(tmp);
- }
- QString dump_sidedata(const AVStream* st, const char* indent)
- {
- QString str;
- char tmp[BUFF_MAXLEN];
- if (!st->codecpar)
- return str;
- if (st->codecpar->nb_coded_side_data)
- {
- snprintf(tmp, sizeof(tmp), "%sSide data:\n", indent);
- str += tmp;
- }
- for (int i = 0; i < st->codecpar->nb_coded_side_data; i++)
- {
- const AVPacketSideData* sd = &st->codecpar->coded_side_data[i];
- snprintf(tmp, sizeof(tmp), "%s ", indent);
- str += tmp;
- switch (sd->type)
- {
- case AV_PKT_DATA_PALETTE:
- str += "palette";
- break;
- case AV_PKT_DATA_NEW_EXTRADATA:
- str += "new extradata";
- break;
- case AV_PKT_DATA_PARAM_CHANGE:
- str += "paramchange: ";
- // dump_paramchange(ctx, sd);
- break;
- case AV_PKT_DATA_H263_MB_INFO:
- str += "H.263 macroblock info";
- break;
- case AV_PKT_DATA_REPLAYGAIN:
- str += "replaygain: ";
- // dump_replaygain(ctx, sd);
- break;
- case AV_PKT_DATA_DISPLAYMATRIX:
- {
- snprintf(tmp, sizeof(tmp), "displaymatrix: rotation of %.2f degrees",
- av_display_rotation_get((const int32_t*)sd->data));
- str += tmp;
- }
- break;
- case AV_PKT_DATA_STEREO3D:
- str += "stereo3d: ";
- // dump_stereo3d(ctx, sd);
- break;
- case AV_PKT_DATA_AUDIO_SERVICE_TYPE:
- str += "audio service type: ";
- // dump_audioservicetype(ctx, sd);
- break;
- case AV_PKT_DATA_QUALITY_STATS:
- {
- snprintf(tmp, sizeof(tmp), "quality factor: %p, pict_type: %c", sd->data,
- av_get_picture_type_char(AVPictureType(sd->data[4])));
- str += tmp;
- }
- break;
- case AV_PKT_DATA_CPB_PROPERTIES:
- str += "cpb: ";
- // dump_cpb(ctx, sd);
- break;
- case AV_PKT_DATA_MASTERING_DISPLAY_METADATA:
- // dump_mastering_display_metadata(ctx, sd);
- break;
- case AV_PKT_DATA_SPHERICAL:
- str += "spherical: ";
- // dump_spherical(ctx, st->codecpar, sd);
- break;
- case AV_PKT_DATA_CONTENT_LIGHT_LEVEL:
- // dump_content_light_metadata(ctx, sd);
- break;
- case AV_PKT_DATA_ICC_PROFILE:
- str += "ICC Profile";
- break;
- case AV_PKT_DATA_DOVI_CONF:
- str += "DOVI configuration record: ";
- // dump_dovi_conf(ctx, sd);
- break;
- case AV_PKT_DATA_S12M_TIMECODE:
- str += "SMPTE ST 12-1:2014: ";
- // dump_s12m_timecode(ctx, st, sd);
- break;
- default:
- {
- snprintf(tmp, sizeof(tmp), "unknown side data type %d, size:%llu bytes",
- sd->type, sd->size);
- str += tmp;
- }
- break;
- }
- str += "\n";
- }
- return str;
- }
|