首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ffplay how to get AVDictionary codec_opts

ffplay how to get AVDictionary codec_opts
EN

Stack Overflow用户
提问于 2018-12-04 20:45:08
回答 2查看 1.5K关注 0票数 0

因为我使用自定义的ffmpeg播放器应用程序(ffmpeg stream decoding - artefacts when not using ffplay)解码伪像,而ffplay显示没有伪像的完美图像,所以我需要以与ffplay相同的方式实现我的播放器。

ffplay.c使用一个

代码语言:javascript
复制
AVDictionary *codec_opts;

它是在cmdutils.c中初始化的(纠正我的错误)。我需要这个字典来模拟ffplay (第2615f行)的编解码器初始化,但我不明白它是如何创建的。有没有办法

a)以ffplay相同的方式包含cmdutils -链接到cmdutils.o最终给我

代码语言:javascript
复制
:-1: error: /.../cmdutils.o: undefined reference to symbol 'swresample_version@@LIBSWRESAMPLE_3'

尽管我使用(QT)包含了libswresample:

代码语言:javascript
复制
LIBS +=-L/usr/local/lib -lavformat -lswscale -lswresample -lavutil -lavcodec 

b)以任何其他方式访问AVDictionary codec_opts?

EN

回答 2

Stack Overflow用户

发布于 2018-12-06 15:18:18

可以,您可以为自己的实现创建和设置AVDictionary *codec_opts

检查以下示例:

1) https://github.com/sparrowli/laimpeg/blob/0a68db7d88c0b42c3df584e66366b4e81d3b31ee/libavutil/tests/dict.c

2) https://github.com/ithinkso117/DotNetPusher/blob/cf24e7e10a0b2fa843b435d3d3b759a7aa049d1d/DotNetPusher.Native/Encoder.cpp

至于包含cmdutils.c,这是行不通的。只能通过API和共享库链接来使用FFmpeg的库。

希望这些能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2020-06-12 02:15:54

在我自己定制的ffmpeg播放器应用程序中,我尝试复制ffplay的AVDictionary编解码器初始化代码,但我不明白它是做什么的。这就是它,但它看起来更像是命令行提供的选项的过滤器,而不是选择选项并启用它们的代码。

代码语言:javascript
复制
int LIBAV_Video::check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
{
    int ret = avformat_match_stream_specifier(s, st, spec);
    if (ret < 0)
        av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
    return ret;
}

//////////////////////////////////////////////////////////////////////////////////////
AVDictionary* LIBAV_Video::filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
                                                                                                AVFormatContext *s, AVStream *st, AVCodec *codec)
{
    AVDictionary    *ret = NULL;
    AVDictionaryEntry *t = NULL;
    int            flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM
                                                                        : 
    AV_OPT_FLAG_DECODING_PARAM;
    char          prefix = 0;
    const AVClass    *cc = avcodec_get_class();

    if (!codec)
        codec              = s->oformat ? avcodec_find_encoder(codec_id)
                                                                      : 
    avcodec_find_decoder(codec_id);

    switch (st->codecpar->codec_type) 
    {
    case AVMEDIA_TYPE_VIDEO:
        prefix  = 'v';
        flags  |= AV_OPT_FLAG_VIDEO_PARAM;
        break;
    case AVMEDIA_TYPE_AUDIO:
        prefix  = 'a';
        flags  |= AV_OPT_FLAG_AUDIO_PARAM;
        break;
    case AVMEDIA_TYPE_SUBTITLE:
        prefix  = 's';
        flags  |= AV_OPT_FLAG_SUBTITLE_PARAM;
        break;
    }

    while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) 
    {
        char *p = strchr(t->key, ':');

        /* check stream specification in opt name */
        if (p)
            switch (check_stream_specifier(s, st, p + 1)) 
            {
            case  1: *p = 0; break;
            case  0:         continue;
            default:         exit(1);   
            }

        if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
                !codec ||
                (codec->priv_class &&
                av_opt_find(&codec->priv_class, t->key, NULL, flags,
                AV_OPT_SEARCH_FAKE_OBJ)))
        {
            av_dict_set(&ret, t->key, t->value, 0);
        }
        else if (t->key[0] == prefix &&
                         av_opt_find(&cc, t->key + 1, NULL, flags,
                         AV_OPT_SEARCH_FAKE_OBJ))
        {
            av_dict_set(&ret, t->key + 1, t->value, 0);
        }
        if (p)
            *p = ':';
    }

    return ret;
}

//////////////////////////////////////////////////////////////////////////////////////
AVDictionary** LIBAV_Video::setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts)
{
    unsigned int i;
    AVDictionary **opts;

    if (!s->nb_streams)
        return NULL;

    opts = (AVDictionary **)av_mallocz_array(s->nb_streams, sizeof(*opts));
    if (!opts) 
    {
        av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n");
        return NULL;
    }

    for (i = 0; i < s->nb_streams; i++)
        opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, s, s->streams[i], NULL);

    return opts;
}

如果任何人知道任何关于识别用于常见用例的选项的编程参考或文档,例如最小回放延迟,将不胜感激。

我发现在自定义代码中获得高质量的ffmpeg libav回放需要解决两个问题: 1)一系列的AVDictionary设置似乎随着每个库的发布而不同,2)来自AVFilter的ffplay图形实现需要复制。我怀疑AVFilter图是必要的,因为它是在关键帧和非关键帧之间进行插值的逻辑,并且似乎对损坏的帧具有某种类型的校正。

下面是AVDictionary设置,它似乎在ffmpeg 4.2.3上工作得很好,但每个版本似乎都不同,我不知道为什么:

代码语言:javascript
复制
  av_dict_set(&mp_opts, "threads", "auto", 0);  // if multi-threading is needed, do it
  av_dict_set( &mp_opts, "refcounted_frames", "1", 0 ); // ffplay sets this
  av_dict_set( &mp_opts, "sync", "video", 0 );  
  av_dict_set( &mp_opts, "fflags", "discardcorrupt", 0 );// sets flag in mp_format_context

    switch (mp_av_player->m_stream_type)
    {
    case 0: // media file
        av_dict_set( &mp_opts, "framerate", "24", 0 );
        av_dict_set( &mp_opts, "scan_all_pmts", "1", 0 );   // ffplay uses this flag
        break;
    case 1: // usb cam
        // av_dict_set(&mp_opts,"show_video_device_dialog","true",0);
        if (usb_format)
        {
            // av_dict_set( &mp_opts, "max_delay", "500000", 0 );   // half second
            // av_dict_set( &mp_opts, "rtbufsize", "106M", 0 );     // a half second of 1280x720x4 
            av_dict_set( &mp_opts, "fflags", "nobuffer", 0 );

            char bsjnk[1024];
            sprintf( bsjnk, "%dx%d", usb_format->m_max_width, usb_format->m_max_height );
            av_dict_set( &mp_opts, "video_size", bsjnk, 0 );
            //
            sprintf( bsjnk, "%1.2f", usb_format->m_max_fps );
            av_dict_set( &mp_opts, "framerate", bsjnk, 0 );
            //
            if (usb_format->m_pixelFormat.size() > 0)
            {
                av_dict_set( &mp_opts, "pixel_format", usb_format->m_pixelFormat.c_str(), 0 );
            }
            else if (usb_format->m_pixelFormat.size() > 0)
            {
                av_dict_set( &mp_opts, "vcodec", usb_format->m_vcodec.c_str(), 0 );
            }
        } 
        else 
        {
            av_dict_set( &mp_opts, "video_size", "640x480", 0 );
            av_dict_set( &mp_opts, "framerate", "30", 0 );
        }
        break;
    case 2: // ip cam
        // av_dict_set( &mp_opts, "flags2", "fast", 0 ); does this cause bad frames?
        av_dict_set( &mp_opts, "max_delay", "100000", 0 );
        av_dict_set( &mp_opts, "flags", "low_delay", 0 );
        // av_dict_set( &mp_opts, "fflags", "flush_packets", 0 );
        // av_dict_set( &mp_opts, "fflags", "nobuffer", 0 ); testing removing this
        av_dict_set( &mp_opts, "rtsp_transport", "tcp", 0 );
        av_dict_set( &mp_opts, "framerate", "29.97", 0 );
        av_dict_set( &mp_opts, "allowed_media_types", "video", 0 );
        break;
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53613335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档