|
|
|
@ -15,6 +15,7 @@ |
|
|
|
#ifdef HAVE_FFMPEG |
|
|
|
#ifdef HAVE_FFMPEG |
|
|
|
#include <libavformat/avformat.h> |
|
|
|
#include <libavformat/avformat.h> |
|
|
|
#include <libavcodec/avcodec.h> |
|
|
|
#include <libavcodec/avcodec.h> |
|
|
|
|
|
|
|
#include <libavcodec/bsf.h> |
|
|
|
#include <libavutil/avutil.h> |
|
|
|
#include <libavutil/avutil.h> |
|
|
|
#include <libavutil/imgutils.h> |
|
|
|
#include <libavutil/imgutils.h> |
|
|
|
#include <libavutil/opt.h> |
|
|
|
#include <libavutil/opt.h> |
|
|
|
@ -66,24 +67,43 @@ int video_extract_thumbnail(const char* src, const char* jpg_out, int max_w) { |
|
|
|
|
|
|
|
|
|
|
|
static pthread_once_t g_ffmpeg_once = PTHREAD_ONCE_INIT; |
|
|
|
static pthread_once_t g_ffmpeg_once = PTHREAD_ONCE_INIT; |
|
|
|
|
|
|
|
|
|
|
|
/* AMF передаёт свой внутренний трейс через AV_LOG_DEBUG. Остальные подробные логи FFmpeg отсекаем. */ |
|
|
|
/* Пропускаем диагностику AMF и существенные поля trace_headers, остальные подробности FFmpeg отсекаем. */ |
|
|
|
static void video_av_log_cb(void* avcl, int level, const char* fmt, va_list vl) { |
|
|
|
static void video_av_log_cb(void* avcl, int level, const char* fmt, va_list vl) { |
|
|
|
const char *encoder = NULL; |
|
|
|
const char *encoder = NULL; |
|
|
|
|
|
|
|
int headers = 0; |
|
|
|
if (level > AV_LOG_WARNING) { |
|
|
|
if (level > AV_LOG_WARNING) { |
|
|
|
if (!debug_should_output(DEBUG_LEVEL_TRACE, DEBUG_CATEGORY_DEBUG)) return; |
|
|
|
if (!debug_should_output(DEBUG_LEVEL_TRACE, DEBUG_CATEGORY_DEBUG)) return; |
|
|
|
if (!avcl || *(const AVClass **)avcl != avcodec_get_class()) return; |
|
|
|
if (!avcl) return; |
|
|
|
const AVCodecContext *codec = avcl; |
|
|
|
if (*(const AVClass **)avcl == av_bsf_get_class()) { |
|
|
|
if (!codec->codec || !codec->codec->name) return; |
|
|
|
const AVBSFContext *filter = avcl; |
|
|
|
const char *name = codec->codec->name; |
|
|
|
if (!filter->filter || strcmp(filter->filter->name, "trace_headers")) return; |
|
|
|
size_t length = strlen(name); |
|
|
|
headers = 1; |
|
|
|
if (length < 4 || strcmp(name + length - 4, "_amf")) return; |
|
|
|
} else { |
|
|
|
encoder = name; |
|
|
|
if (*(const AVClass **)avcl != avcodec_get_class()) return; |
|
|
|
|
|
|
|
const AVCodecContext *codec = avcl; |
|
|
|
|
|
|
|
if (!codec->codec || !codec->codec->name) return; |
|
|
|
|
|
|
|
const char *name = codec->codec->name; |
|
|
|
|
|
|
|
size_t length = strlen(name); |
|
|
|
|
|
|
|
if (length < 4 || strcmp(name + length - 4, "_amf")) return; |
|
|
|
|
|
|
|
encoder = name; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
char buf[1024]; |
|
|
|
char buf[1024]; |
|
|
|
vsnprintf(buf, sizeof(buf), fmt, vl); |
|
|
|
vsnprintf(buf, sizeof(buf), fmt, vl); |
|
|
|
size_t len = strlen(buf); |
|
|
|
size_t len = strlen(buf); |
|
|
|
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) buf[--len] = '\0'; |
|
|
|
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) buf[--len] = '\0'; |
|
|
|
if (encoder) DEBUG_TRACE(DEBUG_CATEGORY_DEBUG, "ffmpeg AMF encoder=%s: %s", encoder, buf); |
|
|
|
if (headers) { |
|
|
|
|
|
|
|
if (!strstr(buf, "Packet:") && !strstr(buf, "init_qp_minus26") && !strstr(buf, "slice_qp_delta") |
|
|
|
|
|
|
|
&& !strstr(buf, "pic_width_in_luma_samples") && !strstr(buf, "pic_height_in_luma_samples") |
|
|
|
|
|
|
|
&& !strstr(buf, "pic_parameter_set_id") && !strstr(buf, "cu_qp_delta_enabled_flag") |
|
|
|
|
|
|
|
&& !strstr(buf, "diff_cu_qp_delta_depth") && !strstr(buf, "slice_type")) return; |
|
|
|
|
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_DEBUG, "ffmpeg headers: %s", buf); |
|
|
|
|
|
|
|
} else if (encoder) { |
|
|
|
|
|
|
|
if (!strstr(buf, "Warning:") && !strstr(buf, "Error:") |
|
|
|
|
|
|
|
&& (strstr(buf, "::SubmitInput() : format") || strstr(buf, "SubmitToEncoder() End: frame pts=") |
|
|
|
|
|
|
|
|| strstr(buf, "::QueryOutput()") || strstr(buf, "QueryOutput() End: frame pts="))) return; |
|
|
|
|
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_DEBUG, "ffmpeg AMF encoder=%s: %s", encoder, buf); |
|
|
|
|
|
|
|
} |
|
|
|
else if (level <= AV_LOG_ERROR) DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf); |
|
|
|
else if (level <= AV_LOG_ERROR) DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf); |
|
|
|
else DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf); |
|
|
|
else DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf); |
|
|
|
} |
|
|
|
} |
|
|
|
|