static void format_line(void *ptr, int level, const char *fmt, va_list vl, char part[3][LINE_SZ], int part_size, int *print_prefix, int type[2]) { AVClass* avc = ptr ? *(AVClass **) ptr : NULL; part[0][0] = part[1][0] = part[2][0] = 0; if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; if (*print_prefix && avc) { if (avc->parent_log_context_offset) { AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + avc->parent_log_context_offset); if (parent && *parent) { snprintf(part[0], part_size, "[%s @ %p] ", (*parent)->item_name(parent), parent); if(type) type[0] = get_category(parent); } } snprintf(part[1], part_size, "[%s @ %p] ", avc->item_name(ptr), ptr); if(type) type[1] = get_category(ptr); } vsnprintf(part[2], part_size, fmt, vl); if(*part[0] || *part[1] || *part[2]) { char lastc = strlen(part[2]) ? part[2][strlen(part[2]) - 1] : 0; *print_prefix = lastc == '\n' || lastc == '\r'; } }
void av_log_wx_callback(void* ptr, int level, const char* fmt, va_list vl) { int av_log_level = AV_LOG_WARNING; AVClass* avc = ptr ? *(AVClass**)ptr : NULL; if (level > av_log_level) return; wxString printstring(wxT("")); if (avc) { printstring.Append(wxString::Format(wxT("[%s @ %p] "), wxString::FromUTF8(avc->item_name(ptr)).c_str(), avc)); } wxString frm(fmt,wxConvLibc); printstring.Append(wxString::FormatV(frm,vl)); wxString cpt; switch (level) { case 0: cpt = wxT("Error"); break; case 1: cpt = wxT("Info"); break; case 2: cpt = wxT("Debug"); break; default: cpt = wxT("Log"); break; } wxLogMessage(wxT("%s: %s"),cpt.c_str(),printstring.c_str()); }
static void ffmpeg_log_cb(void* ptr, int level, const char* fmt, va_list vl) { const char *LOG_SENDER = "ffmpeg"; enum { LOG_LEVEL = 5 }; char buf[100]; int bufsize = sizeof(buf), len; pj_str_t fmt_st; /* Custom callback needs to filter log level by itself */ if (level > av_log_get_level()) return; /* Add original ffmpeg sender to log format */ if (ptr) { AVClass* avc = *(AVClass**)ptr; len = pj_ansi_snprintf(buf, bufsize, "%s: ", avc->item_name(ptr)); bufsize -= len; } /* Copy original log format */ len = pj_ansi_strlen(fmt); if (len > bufsize-1) len = bufsize-1; pj_memcpy(buf+sizeof(buf)-bufsize, fmt, len); bufsize -= len; /* Trim log format */ pj_strset(&fmt_st, buf, sizeof(buf)-bufsize); pj_strrtrim(&fmt_st); buf[fmt_st.slen] = '\0'; pj_log(LOG_SENDER, LOG_LEVEL, buf, vl); }
static void format_line(void *ptr, int level, const char *fmt, va_list vl, AVBPrint part[3], int *print_prefix, int type[2]) { AVClass* avc = ptr ? *(AVClass **) ptr : NULL; av_bprint_init(part+0, 0, 1); av_bprint_init(part+1, 0, 1); av_bprint_init(part+2, 0, 65536); if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; if (*print_prefix && avc) { if (avc->parent_log_context_offset) { AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + avc->parent_log_context_offset); if (parent && *parent) { av_bprintf(part+0, "[%s @ %p] ", (*parent)->item_name(parent), parent); if(type) type[0] = get_category(parent); } } av_bprintf(part+1, "[%s @ %p] ", avc->item_name(ptr), ptr); if(type) type[1] = get_category(ptr); } av_vbprintf(part+2, fmt, vl); if(*part[0].str || *part[1].str || *part[2].str) { char lastc = part[2].len ? part[2].str[part[2].len - 1] : 0; *print_prefix = lastc == '\n' || lastc == '\r'; } }
void av_log_windebug_callback(void* ptr, int level, const char* fmt, va_list vl) { static int print_prefix=1; static int count; static char line[1024] = {0}, prev[1024] = {0}; AVClass* avc = ptr ? *(AVClass**)ptr : NULL; if(level > av_log_get_level()) return; int written = 0; if(print_prefix && avc) { written = snprintf(line, sizeof(line), "[%s @ %p]", avc->item_name(ptr), ptr); } written += vsnprintf(line + written, sizeof(line) - written, fmt, vl); print_prefix = line[written-1] == '\n'; line[sizeof(line) - 1] = 0; if(print_prefix && !strcmp(line, prev)){ count++; return; } if(count > 0){ std::stringstream ss; ss << " Last message repeated " << count << " times\n"; OutputDebugStringA(ss.str().c_str()); count = 0; } OutputDebugStringA(line); strcpy(prev, line); }
static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, va_list vl) { AVClass *avc = ptr ? *(AVClass **)ptr : NULL; int mp_level = av_log_level_to_mp_level(level); // Note: mp_log is thread-safe, but destruction of the log instances is not. pthread_mutex_lock(&log_lock); if (!log_mpv_instance) { pthread_mutex_unlock(&log_lock); // Fallback to stderr vfprintf(stderr, fmt, vl); return; } struct mp_log *log = get_av_log(ptr); if (mp_msg_test(log, mp_level)) { char buffer[4096] = ""; int pos = 0; const char *prefix = avc ? avc->item_name(ptr) : NULL; if (log_print_prefix && prefix) pos = snprintf(buffer, sizeof(buffer), "%s: ", prefix); log_print_prefix = fmt[strlen(fmt) - 1] == '\n'; pos = MPMIN(MPMAX(pos, 0), sizeof(buffer)); vsnprintf(buffer + pos, sizeof(buffer) - pos, fmt, vl); mp_msg(log, mp_level, "%s", buffer); } pthread_mutex_unlock(&log_lock); }
static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, va_list vl) { AVClass *avc = ptr ? *(AVClass **)ptr : NULL; int mp_level = av_log_level_to_mp_level(level); // Note: mp_log is thread-safe, but destruction of the log instances is not. pthread_mutex_lock(&log_lock); if (!log_mpv_instance) { pthread_mutex_unlock(&log_lock); // Fallback to stderr vfprintf(stderr, fmt, vl); return; } struct mp_log *log = get_av_log(ptr); if (mp_msg_test(log, mp_level)) { if (log_print_prefix) mp_msg(log, mp_level, "%s: ", avc ? avc->item_name(ptr) : "?"); log_print_prefix = fmt[strlen(fmt) - 1] == '\n'; mp_msg_va(log, mp_level, fmt, vl); } pthread_mutex_unlock(&log_lock); }
/// libav logging hook void logging_callback(void* ptr, int level, const char* fmt, std::va_list arg_list) { using boost::lexical_cast; AVClass* avc = ptr ? (*reinterpret_cast<AVClass**>(ptr)) : 0; std::string prefix; if (avc) { if (avc->parent_log_context_offset) { AVClass** parent = *reinterpret_cast<AVClass ***> (ptr) + avc->parent_log_context_offset; if (parent && *parent) { prefix += '['; prefix += (*parent)->class_name; prefix += ' '; prefix += (*parent)->item_name(parent); prefix += " @ "; prefix += lexical_cast<std::string>(parent); prefix += "] "; } } prefix += '['; prefix += avc->class_name; prefix += ' '; prefix += avc->item_name(ptr); prefix += " @ "; prefix += lexical_cast<std::string>(ptr); prefix += "] "; } switch(level) { case AV_LOG_PANIC: case AV_LOG_FATAL: case AV_LOG_ERROR: LOG(ERROR) << prefix << stringf(fmt, arg_list).get(); break; case AV_LOG_WARNING: LOG(WARNING) << prefix << stringf(fmt, arg_list).get(); break; case AV_LOG_INFO: VLOG(3) << prefix << stringf(fmt, arg_list).get(); break; case AV_LOG_VERBOSE: VLOG(4) << prefix << stringf(fmt, arg_list).get(); break; case AV_LOG_DEBUG: VLOG(5) << prefix << stringf(fmt, arg_list).get(); break; default: LOG(ERROR) << prefix << "*" << stringf(fmt, arg_list).get(); } }
/* * This function will be called back by Ffmpeg anytime * it wants to log. We then use it to dump * stuff into our own logs. */ static void xuggler_log_callback(void* ptr, int level, const char* fmt, va_list va) { static Logger* ffmpegLogger = 0; AVClass* avc = ptr ? *(AVClass**)ptr : 0; int currentLevel = av_log_get_level(); // fprintf(stderr, "current level: %d; log level: %d\n", level, currentLevel); if (level > currentLevel || currentLevel < AV_LOG_PANIC) // just return return; if (!ffmpegLogger) { Global::lock(); if (!ffmpegLogger) ffmpegLogger = Logger::getStaticLogger( "org.ffmpeg" ); Global::unlock(); } Logger::Level logLevel; if (level <= AV_LOG_ERROR) logLevel = Logger::LEVEL_ERROR; else if (level <= AV_LOG_WARNING) logLevel = Logger::LEVEL_WARN; else if (level <= AV_LOG_INFO) logLevel = Logger::LEVEL_INFO; else if (level <= AV_LOG_DEBUG) logLevel = Logger::LEVEL_DEBUG; else logLevel = Logger::LEVEL_TRACE; // Revise the format string to add additional useful info char revisedFmt[1024]; revisedFmt[sizeof(revisedFmt)-1] = 0; if (avc) { snprintf(revisedFmt, sizeof(revisedFmt), "[%s @ %p] %s", avc->item_name(ptr), ptr, fmt); } else { snprintf(revisedFmt, sizeof(revisedFmt), "%s", fmt); } int len = strlen(revisedFmt); if (len > 0 && revisedFmt[len-1] == '\n') { revisedFmt[len-1]=0; --len; } if (len > 0) // it's not useful to pass in filenames and line numbers here. ffmpegLogger->logVA(0, 0, logLevel, revisedFmt, va); }
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs) { static int print_prefix = 1; AVClass *avc = ptr ? *(AVClass**)ptr : NULL; if (level > av_log_get_level()) return; if (print_prefix && avc) http_log("[%s @ %p]", avc->item_name(ptr), ptr); print_prefix = strstr(fmt, "\n") != NULL; http_vlog(fmt, vargs); }
static int get_category(void *ptr){ AVClass *avc = *(AVClass **) ptr; if( !avc || (avc->version&0xFF)<100 || avc->version < (51 << 16 | 59 << 8) || avc->category >= AV_CLASS_CATEGORY_NB) return AV_CLASS_CATEGORY_NA + 16; if(avc->get_category) return avc->get_category(ptr) + 16; return avc->category + 16; }
static void qtav_ffmpeg_log_callback(void* ctx, int level,const char* fmt, va_list vl) { // AV_LOG_DEBUG is used by ffmpeg developers if (level > AV_LOG_VERBOSE) return; AVClass *c = ctx ? *(AVClass**)ctx : 0; QString qmsg = QString().sprintf("[FFmpeg:%s] ", c ? c->item_name(ctx) : "?") + QString().vsprintf(fmt, vl); qmsg = qmsg.trimmed(); if (level > AV_LOG_WARNING) qDebug() << qmsg; else if (level > AV_LOG_PANIC) qWarning() << qmsg; }
void setOptionsToFFmpegObj(const QVariant& opt, void* obj) { if (!opt.isValid()) return; AVClass *c = obj ? *(AVClass**)obj : 0; if (c) qDebug() << QString("%1.%2 options:").arg(c->class_name).arg(c->item_name(obj)); else qDebug() << "options:"; if (opt.type() == QVariant::Map) { QVariantMap options(opt.toMap()); if (options.isEmpty()) return; QMapIterator<QString, QVariant> i(options); while (i.hasNext()) { i.next(); const QVariant::Type vt = i.value().type(); if (vt == QVariant::Map) continue; const QByteArray key(i.key().toLower().toUtf8()); qDebug("%s=>%s", i.key().toUtf8().constData(), i.value().toByteArray().constData()); if (vt == QVariant::Int || vt == QVariant::UInt || vt == QVariant::Bool) { // QVariant.toByteArray(): "true" or "false", can not recognized by avcodec av_opt_set_int(obj, key.constData(), i.value().toInt(), 0); } else if (vt == QVariant::LongLong || vt == QVariant::ULongLong) { av_opt_set_int(obj, key.constData(), i.value().toLongLong(), 0); } else if (vt == QVariant::Double) { av_opt_set_double(obj, key.constData(), i.value().toDouble(), 0); } } return; } QVariantHash options(opt.toHash()); if (options.isEmpty()) return; QHashIterator<QString, QVariant> i(options); while (i.hasNext()) { i.next(); const QVariant::Type vt = i.value().type(); if (vt == QVariant::Hash) continue; const QByteArray key(i.key().toLower().toUtf8()); qDebug("%s=>%s", i.key().toUtf8().constData(), i.value().toByteArray().constData()); if (vt == QVariant::Int || vt == QVariant::UInt || vt == QVariant::Bool) { av_opt_set_int(obj, key.constData(), i.value().toInt(), 0); } else if (vt == QVariant::LongLong || vt == QVariant::ULongLong) { av_opt_set_int(obj, key.constData(), i.value().toLongLong(), 0); } } }
void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) { static int print_prefix = 1; static int count; static char prev[1024]; char line[1024]; static int is_atty; AVClass* avc = ptr ? *(AVClass **) ptr : NULL; if (level > av_log_level) return; line[0] = 0; #undef fprintf if (print_prefix && 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); print_prefix = strlen(line) && line[strlen(line) - 1] == '\n'; #if HAVE_ISATTY if (!is_atty) is_atty = isatty(2) ? 1 : -1; #endif if (print_prefix && (flags & AV_LOG_SKIP_REPEATED) && !strncmp(line, prev, sizeof line)) { count++; if (is_atty == 1) fprintf(stderr, " Last message repeated %d times\r", count); return; } if (count > 0) { fprintf(stderr, " Last message repeated %d times\n", count); count = 0; } colored_fputs(av_clip(level >> 3, 0, 6), line); av_strlcpy(prev, line, sizeof line); }
static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, va_list vl) { static bool print_prefix = 1; AVClass *avc = ptr ? *(AVClass **)ptr : NULL; int mp_level = av_log_level_to_mp_level(level); int type = extract_msg_type_from_ctx(ptr); if (!mp_msg_test(type, mp_level)) return; if (print_prefix && avc) mp_msg(type, mp_level, "[%s @ %p]", avc->item_name(ptr), avc); print_prefix = fmt[strlen(fmt) - 1] == '\n'; mp_msg_va(type, mp_level, fmt, vl); }
void av_log_wx_callback(void* ptr, int level, const char* fmt, va_list vl) { //Most of this stuff is taken from FFmpeg tutorials and FFmpeg itself int av_log_level = AV_LOG_INFO; AVClass* avc = ptr ? *(AVClass**)ptr : NULL; if (level > av_log_level) return; wxString printstring(wxT("")); if (avc) { printstring.Append(wxString::Format(wxT("[%s @ %p] "), wxString::FromUTF8(avc->item_name(ptr)).c_str(), avc)); } wxString frm(fmt,wxConvLibc); #if defined(__WXMSW__) frm.Replace(wxT("%t"),wxT("%i"),true); //TODO: on Windows vprintf won't handle %t, and probably some others. Investigate. #endif #if defined(wxUSE_UNICODE) // String comes with %s format field and a value in value list is ascii char*. Thus in Unicode configurations // we have to convert %s to %S. frm.Replace(wxT("%s"),wxT("%S"),true); #endif printstring.Append(wxString::FormatV(frm,vl)); wxString cpt; switch (level) { case 0: cpt = wxT("Error"); break; case 1: cpt = wxT("Info"); break; case 2: cpt = wxT("Debug"); break; default: cpt = wxT("Log"); break; } #ifdef EXPERIMENTAL_OD_FFMPEG //if the decoding happens thru OD then this gets called from a non main thread, which means wxLogDebug //will crash. //TODO:find some workaround for the log. perhaps use ODManager as a bridge. for now just print if(!wxThread::IsMain()) printf("%s: %s\n",(char*)cpt.char_str(),(char*)printstring.char_str()); else #endif wxLogDebug(wxT("%s: %s"),cpt.c_str(),printstring.c_str()); }
/** * Format log messages and call the user log callback. Essentially a * reimplementation of libavutil/log.c:av_log_default_callback. */ static void avbin_log_callback(void *ptr, int level, const char *fmt, va_list vl) { static char message[8192]; const char *module = NULL; // if (level > av_log_level || !user_log_callback) if (level > av_log_get_level() || !user_log_callback) return; if (ptr) { AVClass *avc = *(AVClass**) ptr; module = avc->item_name(ptr); } vsnprintf(message, sizeof message, fmt, vl); user_log_callback(module, (AVbinLogLevel) level, message); }
void av_log_my_callback (void* ptr, int level, const char* fmt, va_list vl) { AVClass* avc = ptr ? *(AVClass **) ptr : NULL; if (level == AV_LOG_VERBOSE) { // if (0) { char line[1024]; line[0] = 0; if (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); // vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl); // vsnprintf(line, sizeof(line), fmt, vl); // fputs(fmt, stderr); // fputs(line, stderr); if (strstr(line, "NetConnection.Connect.Success") != NULL) { assert(clock_gettime(CLOCK_MONOTONIC, &connected_time) == 0); } // double i1, i2; // int n = sscanf(line, "Property: <Name: description, STRING: %lf, %lf, %*d, %*d", &i1, &i2); // if (n == 2) { // got_timestamp = true; // // printf("%f, %f, %f\n", i1, i2, i1 - i2); // fprinttfn(stdout, "@diff %f", i1 - i2); // } } // // fprintf(stderr, fmt); //http://libav.org/doxygen/master/log_8c_source.html#l00158 // av_log_default_callback(ptr, level, fmt, vl); }
void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, char *line, int line_size, int *print_prefix) { AVClass* avc = ptr ? *(AVClass **) ptr : NULL; line[0] = 0; if (*print_prefix && avc) { if (avc->parent_log_context_offset) { AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + avc->parent_log_context_offset); if (parent && *parent) { snprintf(line, line_size, "[%s @ %p] ", (*parent)->item_name(parent), parent); } } snprintf(line + strlen(line), line_size - strlen(line), "[%s @ %p] ", avc->item_name(ptr), ptr); } vsnprintf(line + strlen(line), line_size - strlen(line), fmt, vl); *print_prefix = strlen(line) && line[strlen(line) - 1] == '\n'; }
static void fflog(void *ptr, int level, const char *fmt, va_list vl) { static char line[1024]; AVClass *avc = ptr ? *(AVClass**)ptr : NULL; if(!ffmpeglog) return; if(level < AV_LOG_WARNING) level = TRACE_ERROR; else if(level < AV_LOG_DEBUG) level = TRACE_INFO; else level = TRACE_DEBUG; vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl); if(line[strlen(line)-1] != '\n') return; line[strlen(line)-1] = 0; TRACE(level, avc ? avc->item_name(ptr) : "FFmpeg", "%s", line); line[0] = 0; }
int32_t Property :: setProperty(void *aContext, const char* aName, const char *aValue) { int32_t retval = -1; try { if (!aContext) throw std::runtime_error("no context passed in"); if (!aName || !*aName) throw std::runtime_error("empty property name passed to setProperty"); void * target=0; const AVOption *o = av_opt_find2(aContext, aName, 0, PROPERTY_SEARCH_CHILDREN, 1, &target); if (o) { AVClass *c = *(AVClass**)target; (void) c; VS_LOG_TRACE("Found option \"%s\" with help: %s; in unit: %s; object type: %s; instance name: %s", o->name, o->help, o->unit, c->class_name, c->item_name(aContext)); } VS_LOG_TRACE("Setting %s to %s", aName, aValue); retval = av_opt_set(aContext, aName, aValue, PROPERTY_SEARCH_CHILDREN); } catch (std::exception & e) { VS_LOG_DEBUG("Error: %s", e.what()); retval = -1; } return retval; }
void FormatBaseStream::mhive_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) { boost::mutex::scoped_lock log_lock(log_mutex); static int print_prefix = 1; static int count; static char line[4096], prev[4096]; //char ptrString[10]; //char ptrLine[4096]; AVClass* avc = ptr ? *(AVClass**) ptr : NULL; #undef fprintf #ifdef __WIN32__ #define snprintf _snprintf #endif if (print_prefix && avc) { snprintf(line, sizeof (line), "[%s @ %p]", avc->item_name(ptr), ptr); //snprintf(ptrString, sizeof (ptrString), "%p", ptr); } else { line[0] = 0; //ptrString[0] = 0; return; } vsnprintf(line + strlen(line), sizeof (line) - strlen(line), fmt, vl); std::string msg = org::esb::util::StringUtil::trim(line, "\n"); //std::string msgPtr = org::esb::util::StringUtil::trim(line, "\n"); /* if (logMap.count(ptrString)) { if (logMap[ptrString].size() > MAX_HISTORY) { logMap[ptrString].erase(--logMap[ptrString].end()); } } logMap[ptrString].push_front(msgPtr); */ /*filter out unwanted messages by loglevel*/ try{ if(level>av_log_get_level())return; switch (level) { case AV_LOG_DEBUG: LOGDEBUG(msg); break; case AV_LOG_INFO: LOGINFO(msg); break; case AV_LOG_ERROR: LOGERROR(msg); break; case AV_LOG_WARNING: LOGWARN(msg); break; case AV_LOG_PANIC: LOGFATAL(msg); break; case AV_LOG_VERBOSE: LOGTRACE(msg); break; default: LOGERROR("Unknown LogLevel:" << level << " - " << msg); break; } }catch(Poco::AssertionViolationException & ex){ std::cout << "error logging"<< ex.displayText() <<std::endl; //LOGERROR("error in logging") } }
static void myth_av_log(void *ptr, int level, const char* fmt, va_list vl) { if (VERBOSE_LEVEL_NONE) return; static QString full_line(""); static const int msg_len = 255; static QMutex string_lock; uint64_t verbose_mask = VB_GENERAL; LogLevel_t verbose_level = LOG_DEBUG; // determine mythtv debug level from av log level switch (level) { case AV_LOG_PANIC: verbose_level = LOG_EMERG; break; case AV_LOG_FATAL: verbose_level = LOG_CRIT; break; case AV_LOG_ERROR: verbose_level = LOG_ERR; verbose_mask |= VB_LIBAV; break; case AV_LOG_DEBUG: case AV_LOG_VERBOSE: case AV_LOG_INFO: verbose_level = LOG_DEBUG; verbose_mask |= VB_LIBAV; break; case AV_LOG_WARNING: verbose_mask |= VB_LIBAV; break; default: return; } if (!VERBOSE_LEVEL_CHECK(verbose_mask, verbose_level)) return; string_lock.lock(); if (full_line.isEmpty() && ptr) { AVClass* avc = *(AVClass**)ptr; full_line.sprintf("[%s @ %p] ", avc->item_name(ptr), avc); } char str[msg_len+1]; int bytes = vsnprintf(str, msg_len+1, fmt, vl); // check for truncated messages and fix them if (bytes > msg_len) { LOG(VB_GENERAL, LOG_WARNING, QString("Libav log output truncated %1 of %2 bytes written") .arg(msg_len).arg(bytes)); str[msg_len-1] = '\n'; } full_line += QString(str); if (full_line.endsWith("\n")) { LOG(verbose_mask, verbose_level, full_line.trimmed()); full_line.truncate(0); } string_lock.unlock(); }