Expose AMF driver diagnostics and effective encoder settings
This commit is contained in:
1 parent
b8bc9b409a
commit
78b147f806
4 files changed
+86
-14
No files matched your search
+23
-10
@@ -41,6 +41,8 @@ int video_transcode_is_active(void) { return vc_active_get(); }
|
||||
|
||||
/* ─── сборка без ffmpeg: стабы ─── */
|
||||
|
||||
void video_ffmpeg_init(void) {}
|
||||
|
||||
int video_probe(const char* path) { (void)path; return 0; }
|
||||
int video_get_info(const char* path, struct video_info* out) { (void)path; (void)out; return -1; }
|
||||
int video_needs_transcode(const struct video_info* info) { (void)info; return 1; }
|
||||
@@ -64,25 +66,36 @@ int video_extract_thumbnail(const char* src, const char* jpg_out, int max_w) {
|
||||
|
||||
static pthread_once_t g_ffmpeg_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
/* Перехват логов FFmpeg: все сообщения идут в наш debug-лог с категорией video,
|
||||
* иначе ошибки ffmpeg теряются в stderr и не видно причину сбоя транскода. */
|
||||
/* AMF передаёт свой внутренний трейс через AV_LOG_DEBUG. Остальные подробные логи FFmpeg отсекаем. */
|
||||
static void video_av_log_cb(void* avcl, int level, const char* fmt, va_list vl) {
|
||||
(void)avcl;
|
||||
if (level > AV_LOG_WARNING) return; /* отсекаем INFO/VERBOSE/DEBUG/TRACE — демуксер спамит */
|
||||
const char *encoder = NULL;
|
||||
if (level > AV_LOG_WARNING) {
|
||||
if (!debug_should_output(DEBUG_LEVEL_TRACE, DEBUG_CATEGORY_DEBUG)) return;
|
||||
if (!avcl || *(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];
|
||||
vsnprintf(buf, sizeof(buf), fmt, vl);
|
||||
size_t len = strlen(buf);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) buf[--len] = '\0';
|
||||
if (level <= AV_LOG_ERROR) DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf);
|
||||
if (encoder) 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 DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "ffmpeg: %s", buf);
|
||||
}
|
||||
|
||||
static void ffmpeg_init_once(void) {
|
||||
av_log_set_callback(video_av_log_cb);
|
||||
av_log_set_level(AV_LOG_WARNING);
|
||||
av_log_set_level(AV_LOG_DEBUG);
|
||||
avformat_network_init();
|
||||
}
|
||||
|
||||
void video_ffmpeg_init(void) { pthread_once(&g_ffmpeg_once, ffmpeg_init_once); }
|
||||
|
||||
/* строковое описание кода ошибки ffmpeg (используется только в worker-потоке) */
|
||||
static const char* vc_errstr(int err) {
|
||||
static char buf[64];
|
||||
@@ -94,7 +107,7 @@ static const char* vc_errstr(int err) {
|
||||
|
||||
int video_probe(const char* path) {
|
||||
if (!path || !path[0]) return 0;
|
||||
pthread_once(&g_ffmpeg_once, ffmpeg_init_once);
|
||||
video_ffmpeg_init();
|
||||
|
||||
AVFormatContext* fmt = NULL;
|
||||
if (avformat_open_input(&fmt, path, NULL, NULL) != 0) return 0;
|
||||
@@ -117,7 +130,7 @@ int video_get_info(const char* path, struct video_info* out) {
|
||||
if (!out) return -1;
|
||||
memset(out, 0, sizeof(*out));
|
||||
if (!path || !path[0]) return -1;
|
||||
pthread_once(&g_ffmpeg_once, ffmpeg_init_once);
|
||||
video_ffmpeg_init();
|
||||
|
||||
AVFormatContext* fmt = NULL;
|
||||
if (avformat_open_input(&fmt, path, NULL, NULL) != 0) {
|
||||
@@ -445,7 +458,7 @@ static void vc_flush(struct vc_ctx* ctx, struct vc_stream* st) {
|
||||
}
|
||||
|
||||
static int vc_run_transcode(struct vc_ctx* ctx) {
|
||||
pthread_once(&g_ffmpeg_once, ffmpeg_init_once);
|
||||
video_ffmpeg_init();
|
||||
|
||||
int ret = avformat_open_input(&ctx->ifmt, ctx->src, NULL, NULL);
|
||||
if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "video: avformat_open_input failed: %s", vc_errstr(ret)); return -1; }
|
||||
@@ -607,7 +620,7 @@ int video_transcode_start(struct media_async* owner, struct UASYNC* ua, const ch
|
||||
int video_extract_thumbnail(const char* src, const char* jpg_out, int max_w) {
|
||||
if (!src || !src[0] || !jpg_out || !jpg_out[0]) return -1;
|
||||
if (max_w <= 0) max_w = 320;
|
||||
pthread_once(&g_ffmpeg_once, ffmpeg_init_once);
|
||||
video_ffmpeg_init();
|
||||
|
||||
AVFormatContext* fmt = NULL;
|
||||
if (avformat_open_input(&fmt, src, NULL, NULL) != 0) {
|
||||
|
||||
@@ -10,6 +10,10 @@ extern "C" {
|
||||
|
||||
struct UASYNC;
|
||||
|
||||
/* Один раз подключает FFmpeg к общему логу; trace категории debug включает внутренние сообщения AMF.
|
||||
* Можно вызывать из любого потока. В сборке без FFmpeg ничего не делает. */
|
||||
void video_ffmpeg_init(void);
|
||||
|
||||
/* ── целевой профиль: H.264 в MP4, не более 720p / 2 Mbit ── */
|
||||
|
||||
#define VIDEO_TARGET_MAX_WIDTH 1280
|
||||
|
||||
Reference in new issue
Block a user