ffmpeg_init.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. // ***********************************************************/
  2. // ffmpeg_init.cpp
  3. //
  4. // Copy Right @ Steven Huang. All rights reserved.
  5. //
  6. // FFmpeg utils.
  7. // ***********************************************************/
  8. #include "ffmpeg_init.h"
  9. #if !NDEBUG
  10. #define OPEN_FFMPEG_LOG 1
  11. #else
  12. #define OPEN_FFMPEG_LOG 0
  13. #endif
  14. #define PRINT_LIB_INFO(libname, LIBNAME) \
  15. if (true) \
  16. { \
  17. const char* indent = " "; \
  18. unsigned int version = libname##_version(); \
  19. qInfo("%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d", indent, #libname, \
  20. LIB##LIBNAME##_VERSION_MAJOR, LIB##LIBNAME##_VERSION_MINOR, \
  21. LIB##LIBNAME##_VERSION_MICRO, AV_VERSION_MAJOR(version), \
  22. AV_VERSION_MINOR(version), AV_VERSION_MICRO(version)); \
  23. }
  24. #define BUFF_MAXLEN 256
  25. static void log_callback(void* ptr, int level, const char* fmt, va_list vl)
  26. {
  27. if (level > av_log_get_level())
  28. return;
  29. va_list vl2;
  30. char line[1024];
  31. static int print_prefix = 1;
  32. va_copy(vl2, vl);
  33. av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
  34. va_end(vl2);
  35. #if OPEN_FFMPEG_LOG
  36. qInfo("FFMPEG:%s", line);
  37. #endif
  38. }
  39. int ffmpeg_init()
  40. {
  41. av_log_set_flags(AV_LOG_SKIP_REPEATED);
  42. av_log_set_level(AV_LOG_INFO);
  43. av_log_set_callback(log_callback);
  44. // print_ffmpeg_info(AV_LOG_INFO);
  45. check_error(-22);
  46. return 0;
  47. }
  48. void check_error(int error)
  49. {
  50. char errorStr[256] = {0};
  51. qDebug("ENOMEM: %d", AVERROR(ENOMEM));
  52. qDebug("ENOMEM: %d", AVERROR(EINVAL));
  53. qDebug("ENOMEM: %d", AVERROR_OPTION_NOT_FOUND);
  54. av_strerror(error, errorStr, sizeof(errorStr));
  55. }
  56. void print_ffmpeg_info()
  57. {
  58. // ffmpeg-snapshot_0401
  59. qInfo("%s version %s", "ffmpeg", FFMPEG_VERSION);
  60. PRINT_LIB_INFO(avutil, AVUTIL);
  61. PRINT_LIB_INFO(avcodec, AVCODEC);
  62. PRINT_LIB_INFO(avformat, AVFORMAT);
  63. // PRINT_LIB_INFO(avdevice, AVDEVICE);
  64. // PRINT_LIB_INFO(avfilter, AVFILTER);
  65. PRINT_LIB_INFO(swscale, SWSCALE);
  66. PRINT_LIB_INFO(swresample, SWRESAMPLE);
  67. qInfo("");
  68. }
  69. QString dump_format(AVFormatContext* ic, int index, const char* url, int is_output)
  70. {
  71. QString str;
  72. char tmp[BUFF_MAXLEN];
  73. const char* indent = " ";
  74. uint8_t* printed = nullptr;
  75. if (!ic)
  76. {
  77. qErrnoWarning("invalid parameter!");
  78. goto fail;
  79. }
  80. if (!url || !url[0])
  81. {
  82. qErrnoWarning("url is invalid!");
  83. goto fail;
  84. }
  85. printed = ic->nb_streams ? (uint8_t*)av_mallocz(ic->nb_streams) : nullptr;
  86. if (ic->nb_streams && !printed)
  87. goto fail;
  88. snprintf(tmp, sizeof(tmp), "%s #%d, %s, %s '%s':",
  89. is_output ? "Output" : "Input", index,
  90. is_output ? ic->oformat->name : ic->iformat->name,
  91. is_output ? "to" : "from", url);
  92. str += tmp;
  93. str += "\n";
  94. str += dump_metadata(ic->metadata, indent);
  95. if (!is_output)
  96. {
  97. snprintf(tmp, sizeof(tmp), "%sDuration: ", indent);
  98. str += tmp;
  99. if (ic->duration != AV_NOPTS_VALUE)
  100. {
  101. int64_t hours, mins, secs, us;
  102. int64_t duration =
  103. ic->duration + (ic->duration <= INT64_MAX - 5000 ? 5000 : 0);
  104. secs = duration / AV_TIME_BASE;
  105. us = duration % AV_TIME_BASE;
  106. mins = secs / 60;
  107. secs %= 60;
  108. hours = mins / 60;
  109. mins %= 60;
  110. snprintf(tmp, sizeof(tmp), "%02lld:%02lld:%02lld.%02lld", hours, mins,
  111. secs, (100 * us) / AV_TIME_BASE);
  112. str += tmp;
  113. }
  114. else
  115. {
  116. str += "N/A";
  117. }
  118. if (ic->start_time != AV_NOPTS_VALUE)
  119. {
  120. int secs, us;
  121. secs = llabs(ic->start_time / AV_TIME_BASE);
  122. us = llabs(ic->start_time % AV_TIME_BASE);
  123. // av_log(nullptr, AV_LOG_INFO, ", start: %s%d.%06d",
  124. // ic->start_time >= 0 ? "" : "-", secs, (int)av_rescale(us, 1000000,
  125. // AV_TIME_BASE));
  126. snprintf(tmp, sizeof(tmp), ", start: %s%d.%06d",
  127. ic->start_time >= 0 ? "" : "-", secs,
  128. (int)av_rescale(us, 1000000, AV_TIME_BASE));
  129. str += tmp;
  130. }
  131. str += ", bitrate: ";
  132. if (ic->bit_rate)
  133. {
  134. snprintf(tmp, sizeof(tmp), "%lld kb/s", ic->bit_rate / 1000);
  135. str += tmp;
  136. }
  137. else
  138. str += "N/A";
  139. str += "\n";
  140. }
  141. if (ic->nb_chapters)
  142. {
  143. snprintf(tmp, sizeof(tmp), "%sChapters:\n", indent);
  144. str += tmp;
  145. }
  146. for (unsigned int i = 0; i < ic->nb_chapters; i++)
  147. {
  148. const AVChapter* ch = ic->chapters[i];
  149. snprintf(tmp, sizeof(tmp), " Chapter #%d:%d: start %f, end %f\n", index,
  150. i, ch->start * av_q2d(ch->time_base),
  151. ch->end * av_q2d(ch->time_base));
  152. str += tmp;
  153. str += dump_metadata(ch->metadata, " ");
  154. }
  155. if (ic->nb_programs)
  156. {
  157. unsigned int j, k, total = 0;
  158. for (j = 0; j < ic->nb_programs; j++)
  159. {
  160. const AVProgram* program = ic->programs[j];
  161. const AVDictionaryEntry* name =
  162. av_dict_get(program->metadata, "name", nullptr, 0);
  163. snprintf(tmp, sizeof(tmp), " Program %d %s\n", program->id,
  164. name ? name->value : "");
  165. str += tmp;
  166. str += dump_metadata(program->metadata, " ");
  167. for (k = 0; k < program->nb_stream_indexes; k++)
  168. {
  169. str +=
  170. dump_stream_format(ic, program->stream_index[k], index, is_output);
  171. printed[program->stream_index[k]] = 1;
  172. }
  173. total += program->nb_stream_indexes;
  174. }
  175. if (total < ic->nb_streams)
  176. {
  177. str += " No Program\n";
  178. }
  179. }
  180. str += "\n";
  181. for (unsigned int i = 0; i < ic->nb_streams; i++)
  182. {
  183. if (!printed[i])
  184. {
  185. str += dump_stream_format(ic, i, index, is_output);
  186. str += "\n";
  187. }
  188. }
  189. return str;
  190. fail:
  191. return QString("");
  192. }
  193. QString dump_metadata(const AVDictionary* m, const char* indent)
  194. {
  195. QString str;
  196. char tmp[BUFF_MAXLEN];
  197. if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", nullptr, 0)))
  198. {
  199. const AVDictionaryEntry* tag = nullptr;
  200. snprintf(tmp, sizeof(tmp), "%sMetadata:\n", indent);
  201. str += tmp;
  202. while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)))
  203. {
  204. if (strcmp("language", tag->key))
  205. {
  206. const char* p = tag->value;
  207. // av_log(ctx, AV_LOG_INFO,"%s %-16s: ", indent, tag->key);
  208. snprintf(tmp, sizeof(tmp), "%s %-16s: ", indent, tag->key);
  209. str += tmp;
  210. while (*p)
  211. {
  212. char tmp_str[256];
  213. size_t len = strcspn(p, "\x8\xa\xb\xc\xd");
  214. av_strlcpy(tmp_str, p, FFMIN(sizeof(tmp_str), len + 1));
  215. // str += "%s", tmp);
  216. snprintf(tmp, sizeof(tmp), "%s", tmp_str);
  217. str += tmp;
  218. p += len;
  219. if (*p == 0xd)
  220. str += " ";
  221. if (*p == 0xa)
  222. str += "\n%s %-16s: ";
  223. if (*p)
  224. p++;
  225. }
  226. str += "\n";
  227. }
  228. }
  229. }
  230. return str;
  231. }
  232. QString dump_stream_format(const AVFormatContext* ic, int i, int index, int is_output)
  233. {
  234. QString str;
  235. char tmp[BUFF_MAXLEN];
  236. char buf[256];
  237. int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
  238. const AVStream* st = ic->streams[i];
  239. // const FFStream* const sti = cffstream(st);
  240. const AVDictionaryEntry* lang =
  241. av_dict_get(st->metadata, "language", nullptr, 0);
  242. const char* separator = (const char*)ic->dump_separator;
  243. AVCodecContext* avctx;
  244. // AVCodecContext* st_avctx = (AVCodecContext*)st->priv_data;
  245. int ret;
  246. avctx = avcodec_alloc_context3(nullptr);
  247. if (!avctx)
  248. goto fail;
  249. ret = avcodec_parameters_to_context(avctx, st->codecpar);
  250. if (ret < 0)
  251. {
  252. avcodec_free_context(&avctx);
  253. goto fail;
  254. }
  255. // Fields which are missing from AVCodecParameters need to be taken from the
  256. // AVCodecContext
  257. /*
  258. avctx->properties = st_avctx->properties;
  259. avctx->codec = st_avctx->codec;
  260. avctx->qmin = st_avctx->qmin;
  261. avctx->qmax = st_avctx->qmax;
  262. avctx->coded_width = st_avctx->coded_width;
  263. avctx->coded_height = st_avctx->coded_height;
  264. if (separator)
  265. av_opt_set(avctx, "dump_separator", separator, 0);*/
  266. avcodec_string(buf, sizeof(buf), avctx, is_output);
  267. avcodec_free_context(&avctx);
  268. snprintf(tmp, sizeof(tmp), " Stream #%d:%d", index, i);
  269. str += tmp;
  270. if (flags & AVFMT_SHOW_IDS)
  271. {
  272. snprintf(tmp, sizeof(tmp), "[0x%x]", st->id);
  273. str += tmp;
  274. }
  275. if (lang)
  276. {
  277. snprintf(tmp, sizeof(tmp), "(%s)", lang->value);
  278. str += tmp;
  279. }
  280. snprintf(tmp, sizeof(tmp), ": %s", buf);
  281. str += tmp;
  282. if (st->sample_aspect_ratio.num &&
  283. av_cmp_q(st->sample_aspect_ratio, st->codecpar->sample_aspect_ratio))
  284. {
  285. AVRational display_aspect_ratio;
  286. av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
  287. st->codecpar->width * (int64_t)st->sample_aspect_ratio.num,
  288. st->codecpar->height * (int64_t)st->sample_aspect_ratio.den,
  289. 1024 * 1024);
  290. snprintf(tmp, sizeof(tmp), ", SAR %d:%d DAR %d:%d",
  291. st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
  292. display_aspect_ratio.num, display_aspect_ratio.den);
  293. str += tmp;
  294. }
  295. if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
  296. {
  297. int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
  298. int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
  299. int tbn = st->time_base.den && st->time_base.num;
  300. if (fps || tbr || tbn)
  301. {
  302. snprintf(tmp, sizeof(tmp), "%s", separator);
  303. str += tmp;
  304. }
  305. if (fps)
  306. str +=
  307. print_fps(av_q2d(st->avg_frame_rate), tbr || tbn ? "fps, " : "fps");
  308. if (tbr)
  309. str += print_fps(av_q2d(st->r_frame_rate), tbn ? "tbr, " : "tbr");
  310. if (tbn)
  311. str += print_fps(1 / av_q2d(st->time_base), "tbn");
  312. }
  313. if (st->disposition & AV_DISPOSITION_DEFAULT)
  314. str += " (default)";
  315. if (st->disposition & AV_DISPOSITION_DUB)
  316. str += " (dub)";
  317. if (st->disposition & AV_DISPOSITION_ORIGINAL)
  318. str += " (original)";
  319. if (st->disposition & AV_DISPOSITION_COMMENT)
  320. str += " (comment)";
  321. if (st->disposition & AV_DISPOSITION_LYRICS)
  322. str += " (lyrics)";
  323. if (st->disposition & AV_DISPOSITION_KARAOKE)
  324. str += " (karaoke)";
  325. if (st->disposition & AV_DISPOSITION_FORCED)
  326. str += " (forced)";
  327. if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
  328. str += " (hearing impaired)";
  329. if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
  330. str += " (visual impaired)";
  331. if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
  332. str += " (clean effects)";
  333. if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
  334. str += " (attached pic)";
  335. if (st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS)
  336. str += " (timed thumbnails)";
  337. if (st->disposition & AV_DISPOSITION_CAPTIONS)
  338. str += " (captions)";
  339. if (st->disposition & AV_DISPOSITION_DESCRIPTIONS)
  340. str += " (descriptions)";
  341. if (st->disposition & AV_DISPOSITION_METADATA)
  342. str += " (metadata)";
  343. if (st->disposition & AV_DISPOSITION_DEPENDENT)
  344. str += " (dependent)";
  345. if (st->disposition & AV_DISPOSITION_STILL_IMAGE)
  346. str += " (still image)";
  347. str += "\n";
  348. str += dump_metadata(st->metadata, " ");
  349. str += dump_sidedata(st, " ");
  350. return str;
  351. fail:
  352. return QString("");
  353. }
  354. QString print_fps(double d, const char* postfix)
  355. {
  356. char tmp[BUFF_MAXLEN];
  357. uint64_t v = lrintf(d * 100);
  358. if (!v)
  359. {
  360. snprintf(tmp, sizeof(tmp), "%1.4f %s", d, postfix);
  361. }
  362. else if (v % 100)
  363. {
  364. snprintf(tmp, sizeof(tmp), "%3.2f %s", d, postfix);
  365. }
  366. else if (v % (100 * 1000))
  367. {
  368. snprintf(tmp, sizeof(tmp), "%1.0f %s", d, postfix);
  369. }
  370. else
  371. {
  372. snprintf(tmp, sizeof(tmp), "%1.0fk %s", d / 1000, postfix);
  373. }
  374. return QString(tmp);
  375. }
  376. QString dump_sidedata(const AVStream* st, const char* indent)
  377. {
  378. QString str;
  379. char tmp[BUFF_MAXLEN];
  380. if (!st->codecpar)
  381. return str;
  382. if (st->codecpar->nb_coded_side_data)
  383. {
  384. snprintf(tmp, sizeof(tmp), "%sSide data:\n", indent);
  385. str += tmp;
  386. }
  387. for (int i = 0; i < st->codecpar->nb_coded_side_data; i++)
  388. {
  389. const AVPacketSideData* sd = &st->codecpar->coded_side_data[i];
  390. snprintf(tmp, sizeof(tmp), "%s ", indent);
  391. str += tmp;
  392. switch (sd->type)
  393. {
  394. case AV_PKT_DATA_PALETTE:
  395. str += "palette";
  396. break;
  397. case AV_PKT_DATA_NEW_EXTRADATA:
  398. str += "new extradata";
  399. break;
  400. case AV_PKT_DATA_PARAM_CHANGE:
  401. str += "paramchange: ";
  402. // dump_paramchange(ctx, sd);
  403. break;
  404. case AV_PKT_DATA_H263_MB_INFO:
  405. str += "H.263 macroblock info";
  406. break;
  407. case AV_PKT_DATA_REPLAYGAIN:
  408. str += "replaygain: ";
  409. // dump_replaygain(ctx, sd);
  410. break;
  411. case AV_PKT_DATA_DISPLAYMATRIX:
  412. {
  413. snprintf(tmp, sizeof(tmp), "displaymatrix: rotation of %.2f degrees",
  414. av_display_rotation_get((const int32_t*)sd->data));
  415. str += tmp;
  416. }
  417. break;
  418. case AV_PKT_DATA_STEREO3D:
  419. str += "stereo3d: ";
  420. // dump_stereo3d(ctx, sd);
  421. break;
  422. case AV_PKT_DATA_AUDIO_SERVICE_TYPE:
  423. str += "audio service type: ";
  424. // dump_audioservicetype(ctx, sd);
  425. break;
  426. case AV_PKT_DATA_QUALITY_STATS:
  427. {
  428. snprintf(tmp, sizeof(tmp), "quality factor: %p, pict_type: %c", sd->data,
  429. av_get_picture_type_char(AVPictureType(sd->data[4])));
  430. str += tmp;
  431. }
  432. break;
  433. case AV_PKT_DATA_CPB_PROPERTIES:
  434. str += "cpb: ";
  435. // dump_cpb(ctx, sd);
  436. break;
  437. case AV_PKT_DATA_MASTERING_DISPLAY_METADATA:
  438. // dump_mastering_display_metadata(ctx, sd);
  439. break;
  440. case AV_PKT_DATA_SPHERICAL:
  441. str += "spherical: ";
  442. // dump_spherical(ctx, st->codecpar, sd);
  443. break;
  444. case AV_PKT_DATA_CONTENT_LIGHT_LEVEL:
  445. // dump_content_light_metadata(ctx, sd);
  446. break;
  447. case AV_PKT_DATA_ICC_PROFILE:
  448. str += "ICC Profile";
  449. break;
  450. case AV_PKT_DATA_DOVI_CONF:
  451. str += "DOVI configuration record: ";
  452. // dump_dovi_conf(ctx, sd);
  453. break;
  454. case AV_PKT_DATA_S12M_TIMECODE:
  455. str += "SMPTE ST 12-1:2014: ";
  456. // dump_s12m_timecode(ctx, st, sd);
  457. break;
  458. default:
  459. {
  460. snprintf(tmp, sizeof(tmp), "unknown side data type %d, size:%llu bytes",
  461. sd->type, sd->size);
  462. str += tmp;
  463. }
  464. break;
  465. }
  466. str += "\n";
  467. }
  468. return str;
  469. }