FFmpeg av_dump_format 码流详情打印和代码剖析
  3cAxQ5E22S4z 2023年11月02日 33 0

说明

        一般使用av_find_stream_info函数探测码流格式,它的作用是为pFormatContext->streams填充上正确的音视频格式信息。可以通过av_dump_format函数将音视频数据格式通过av_log输出到指定的文件或者控制台,方便开发者了解输入的视音频格式,对于程序的调用,删除该函数的调用没有任何的影响


声明

/**
 * Print detailed information about the input or output format, such as
 * duration, bitrate, streams, container, programs, metadata, side data,
 * codec and time base(打印输入或者输出格式的信息,例如视频总时长,波特率,流,容器,程序,元数据,边数据,编码器,时间戳).
 *
 * @param ic        the context to analyze(被分析的视音频上下文)
 * @param index     index of the stream to dump information about(需要解析的流索引号,例如0是视频流,1是音频流)
 * @param url       the URL to print, such as source or destination file(打印URL,例如源文件或者目的文件)
 * @param is_output Select whether the specified context is an input(0) or output(1)(指定的视音频上下文是输入流(0)还是输出流(1))
 */
void av_dump_format(AVFormatContext *ic,
                    int index,
                    const char *url,
                    int is_output);


调用代码

av_dump_format(pFormatContext, 0, "", 0);

 注意:最后一个参数如果是输入流取值0,如果是输出流取值1


日志输出

通过av_log_set_callback设置日志文件输出,输出的结果如下:

Input #0, h264, from '':
  Duration: N/A, bitrate: N/A
    Stream #0:0, 0, 1/1200000: Video: h264 (Baseline), yuvj420p, 1920x1080, 25 fps, 0.04 tbr, 1200k tbn

当前没有打印视频总时长是因为这是h264裸留数据


代码剖析

void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output)
{
    int i;
    uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL;
    if (ic->nb_streams && !printed)
        return;
//如果is_output是0,说明是输入流
    av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
           is_output ? "Output" : "Input",
           index,
           is_output ? ic->oformat->name : ic->iformat->name,
           is_output ? "to" : "from", url);
    dump_metadata(NULL, ic->metadata, "  ");
//如果is_output指定为0,开始计算视频总时长
    if (!is_output) {
        av_log(NULL, AV_LOG_INFO, "  Duration: ");
//如果上下文中的总时长字段有效,说明不是h264裸留,h264裸留是没有dts/pts字段数据的,开始计算视频总时长
        if (ic->duration != AV_NOPTS_VALUE) {
            int hours, mins, secs, us;
            int64_t duration = ic->duration + (ic->duration <= INT64_MAX - 5000 ? 5000 : 0);
            secs  = duration / AV_TIME_BASE;
            us    = duration % AV_TIME_BASE;
            mins  = secs / 60;
            secs %= 60;
            hours = mins / 60;
            mins %= 60;
            av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs,
                   (100 * us) / AV_TIME_BASE);
        } else {
            av_log(NULL, AV_LOG_INFO, "N/A");
        }
       //判断开始是否开始时间有效
        if (ic->start_time != AV_NOPTS_VALUE) {
            int secs, us;
            av_log(NULL, AV_LOG_INFO, ", start: ");
            secs = llabs(ic->start_time / AV_TIME_BASE);
            us   = llabs(ic->start_time % AV_TIME_BASE);
            av_log(NULL, AV_LOG_INFO, "%s%d.%06d",
                   ic->start_time >= 0 ? "" : "-",
                   secs,
                   (int) av_rescale(us, 1000000, AV_TIME_BASE));
        }
        av_log(NULL, AV_LOG_INFO, ", bitrate: ");
        if (ic->bit_rate)
            av_log(NULL, AV_LOG_INFO, "%"PRId64" kb/s", ic->bit_rate / 1000);
        else
            av_log(NULL, AV_LOG_INFO, "N/A");
        av_log(NULL, AV_LOG_INFO, "\n");
    }
    for (i = 0; i < ic->nb_chapters; i++) {
        AVChapter *ch = ic->chapters[i];
        av_log(NULL, AV_LOG_INFO, "    Chapter #%d:%d: ", index, i);
        av_log(NULL, AV_LOG_INFO,
               "start %f, ", ch->start * av_q2d(ch->time_base));
        av_log(NULL, AV_LOG_INFO,
               "end %f\n", ch->end * av_q2d(ch->time_base));
        dump_metadata(NULL, ch->metadata, "    ");
    }
    if (ic->nb_programs) {
        int j, k, total = 0;
        for (j = 0; j < ic->nb_programs; j++) {
            AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata,
                                                  "name", NULL, 0);
            av_log(NULL, AV_LOG_INFO, "  Program %d %s\n", ic->programs[j]->id,
                   name ? name->value : "");
            dump_metadata(NULL, ic->programs[j]->metadata, "    ");
            for (k = 0; k < ic->programs[j]->nb_stream_indexes; k++) {
                dump_stream_format(ic, ic->programs[j]->stream_index[k],
                                   index, is_output);
                printed[ic->programs[j]->stream_index[k]] = 1;
            }
            total += ic->programs[j]->nb_stream_indexes;
        }
        if (total < ic->nb_streams)
            av_log(NULL, AV_LOG_INFO, "  No Program\n");
    }
    for (i = 0; i < ic->nb_streams; i++)
        if (!printed[i])
            dump_stream_format(ic, i, index, is_output);
    av_free(printed);
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  utcwpaXdbjbR   2023年11月02日   51   0   0 html选择器ffmpeg
3cAxQ5E22S4z