[转]ffmpeg日志注入

原文链接:https://my.oschina.net/hava/blog/3127182

 

编者注

由于需要把FFmpeg引入Unity,则使用FFmpeg.AutoGen。独立运行demo没有问题,正常运行,但是相似的代码移入Unity 发生问题。特查询记录。

问题定位

FFmpeg.AutoGen尝试

先在顶层进行尝试,

FFmpeg 源代码分析

Generic error in an external library

由于不好定位,则直接从Exception信息开始。
error.h 57

#define AVERROR_EXTERNAL           FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library

libavutil/error.c

static const struct error_entry error_entries[] = {
	......
    { ERROR_TAG(EXTERNAL),           "Generic error in an external library"           },
	......

能够看到错误标签是AVERROR_EXTERNAL,但是发现有很多地方均使用该内容。则需要方法结合进行判断。

avcodec_open2

头文件:libavcodec/avcodec.h 4318

/**
 * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
 * function the context has to be allocated with avcodec_alloc_context3().
 *
 * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
 * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
 * retrieving a codec.
 *
 * @warning This function is not thread safe!
 *
 * @note Always call this function before using decoding routines (such as
 * @ref avcodec_receive_frame()).
 *
 * @code
 * avcodec_register_all();
 * av_dict_set(&opts, "b", "2.5M", 0);
 * codec = avcodec_find_decoder(AV_CODEC_ID_H264);
 * if (!codec)
 *     exit(1);
 *
 * context = avcodec_alloc_context3(codec);
 *
 * if (avcodec_open2(context, codec, opts) < 0)
 *     exit(1);
 * @endcode
 *
 * @param avctx The context to initialize.
 * @param codec The codec to open this context for. If a non-NULL codec has been
 *              previously passed to avcodec_alloc_context3() or
 *              for this context, then this parameter MUST be either NULL or
 *              equal to the previously passed codec.
 * @param options A dictionary filled with AVCodecContext and codec-private options.
 *                On return this object will be filled with options that were not found.
 *
 * @return zero on success, a negative value on error
 * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
 *      av_dict_set(), av_opt_find().
 */
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

源代码:libavcodec/utils.c 542

int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{
......
}

头文件翻译如下: 初始化AVCodecContext时需要AVCodec。在使用方法前,context必须使用avcodec_alloc_context3()分配内存。

函数avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),avcodec_find_decoder()avcodec_find_encoder()提供搜索解码器的简单方法。

警告:该函数不是线程安全的!

注意:在解码前调用本方法(例如avcodec_receive_frame()

 avcodec_register_all();
 av_dict_set(&opts, "b", "2.5M", 0);
 codec = avcodec_find_decoder(AV_CODEC_ID_H264);
 if (!codec)
     exit(1);

 context = avcodec_alloc_context3(codec);

 if (avcodec_open2(context, codec, opts) < 0)
      exit(1);

参数:avctx需要初始化
参数:codec 访问内容的编码器。如果不为空编码器将会:

  1. 给avcodec_alloc_context3()提供过
  2. 对于context而言,这个参数要么为null要么和以前传递过编解码器相同。

参数:options 充满的AVCodecContext和私有编码选项的字典
返回:返回0为成功;错误返回负数
参考:avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),av_dict_set(), av_opt_find()

被遗忘的日志

虽然编写了日志注入,但是忘记了日志的初始化。则重新配置日志初始化。日志注入代码

using System;
using System.Runtime.InteropServices;

namespace FFmpeg.AutoGen.Utils
{
    public class FFmpegLogging
    {
        public static unsafe void SetupLogging()
        {
            ffmpeg.av_log_set_level(ffmpeg.AV_LOG_VERBOSE);

            // do not convert to local function
            av_log_set_callback_callback logCallback = (p0, level, format, vl) =>
            {
                if (level > ffmpeg.av_log_get_level()) return;

                var lineSize = 1024;
                var lineBuffer = stackalloc byte[lineSize];
                var printPrefix = 1;
                ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
                var line = Marshal.PtrToStringAnsi((IntPtr) lineBuffer);

                if (logger != null)
                {
                    logger(line);
                }
            };

            ffmpeg.av_log_set_callback(logCallback);
        }

        public delegate void SelfLogger(string line);

        public static SelfLogger logger;
    }
}

日志初始化

FFmpegLogging.logger += delegate(string line) {
      logger.info(line);
}
FFmpegLogging.SetupLogging();

运行结果

运行结果打印出了FFmpeg的错误内容:

[libx264 @ 00000006681c0] width not divisible by 2(1283x537)

附录

How to decode MP4 file use GPU use ffmpeg.autogen?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值