FFmpeg+javacpp+javacv使用

FFmpeg+javacpp+javacv使用

  • Bytedeco官网案例
  • 1、导入opencv、ffmpeg依赖包
  • [2、FFmpeg 数据结构](#2、FFmpeg 数据结构)
    • [2.1 AVFormatContext 格式化I/O上下文](#2.1 AVFormatContext 格式化I/O上下文)
      • [2.1.1 metadata](#2.1.1 metadata)
      • [2.1.2 Duration、start、bitrate等其他信息](#2.1.2 Duration、start、bitrate等其他信息)
      • [2.1.3 dump信息](#2.1.3 dump信息)

Bytedeco
GitHub:javacpp

Bytedeco官网案例

FFmpeg -- [示例用法] [API] -- 一个完整的跨平台解决方案,用于录制、转换和流式传输音频和视频

FFmpeg 6.1.1 http://ffmpeg.org/ 关于 FFmpeg
JavaCPP Presets for FFmpeg 6.1.1-1.5.10 API

javacv:https://github.com/bytedeco/javacv

坑哧吭坑: 这可能是最详细的javaCV-FFmpeg防踩坑入门了
javaCV入门指南
雷霄骅(leixiaohua1020)的专栏 FFmpeg
FFmpeg - 打造一款万能的音乐播放器

1、导入opencv、ffmpeg依赖包

xml 复制代码
ext {
    javacvVersion = '1.5.9'
    ffmpegVersion = '6.0'
    windowsVersion = 'windows-x86_64'
}

dependencies {
    /* javacv + FFmpeg */
    // implementation group: 'org.bytedeco', name: 'javacv-platform', version: "$javacvVersion"
    implementation "org.bytedeco:javacpp:${javacvVersion}:${windowsVersion}"
    implementation "org.bytedeco:javacv:${javacvVersion}"
    implementation "org.bytedeco:ffmpeg:${ffmpegVersion}-${javacvVersion}"
    implementation "org.bytedeco:ffmpeg:${ffmpegVersion}-${javacvVersion}:${windowsVersion}"

    testImplementation platform('org.junit:junit-bom:5.9.1')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}

2、FFmpeg 数据结构

2.1 AVFormatContext 格式化I/O上下文

这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。其中nb_streamsstreams所表示的AVStream结构指针数组包含了所有内嵌媒体流的描述;iformatoformat指向对应的demuxer和muxer指针;pb则指向一个控制底层数据读写的ByteIOContext结构。 start_timeduration是从streams数组的各个AVStream中推断出的多媒体文件的起始时间和长度,以微妙为单位。 通常,这个结构由av_open_input_file在内部创建并以缺省值初始化部分成员。但是,如果调用者希望自己创建该结构,则需要显式为该结构的一些成员置缺省值;如果没有缺省值的话,会导致之后的动作产生异常。

java 复制代码
String url = "C:\\Users\\Administrator\\Desktop\\Let Me Down Slowly.mp3";
// 解封装上下文
AVFormatContext pFormatCtx = new AVFormatContext(null);
if (null == pFormatCtx) {
    XLog.e("获取解封装上下文失败");
    return;
}

// 打开流媒体
if (avformat_open_input(pFormatCtx, url, null, null) != 0) {
    XLog.e("打开媒体失败");
    return;
}

// 读取流媒体数据,以获得流的信息
if (avformat_find_stream_info(pFormatCtx, (PointerPointer<Pointer>) null) < 0) {
    XLog.e("获得媒体流信息失败");
    return;
}

2.1.1 metadata

java 复制代码
AVDictionaryEntry tag = null;
tag = av_dict_get(pFormatCtx.metadata(), "", tag, AV_DICT_IGNORE_SUFFIX);
while (tag != null) {
    XLog.d("tag.key : " + tag.key().getString() + "; tag.value : " + tag.value().getString());
    tag = av_dict_get(pFormatCtx.metadata(), "", tag, AV_DICT_IGNORE_SUFFIX);
}

2.1.2 Duration、start、bitrate等其他信息

时间基准 public static final int AV_TIME_BASE = 1000000;

java 复制代码
XLog.d("pFormatCtx url() = " + pFormatCtx.url().getString());
XLog.d("pFormatCtx start_time() = " + pFormatCtx.start_time());
XLog.d("pFormatCtx duration() = " + pFormatCtx.duration());
XLog.d("pFormatCtx bit_rate() = " + pFormatCtx.bit_rate());

2.1.3 dump信息

av_dump_format(pFormatCtx, 0, url, 0);

源码ffmpeg-6.0\libavformat\dump.c

cpp 复制代码
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;

    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, "  ");

    if (!is_output) {
        av_log(NULL, AV_LOG_INFO, "  Duration: ");
        if (ic->duration != AV_NOPTS_VALUE) {
            int64_t 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, "%02"PRId64":%02"PRId64":%02"PRId64".%02"PRId64"", 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");
    }

    if (ic->nb_chapters)
        av_log(NULL, AV_LOG_INFO, "  Chapters:\n");
    for (i = 0; i < ic->nb_chapters; i++) {
        const 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++) {
            const AVProgram *program = ic->programs[j];
            const AVDictionaryEntry *name = av_dict_get(program->metadata,
                                                        "name", NULL, 0);
            av_log(NULL, AV_LOG_INFO, "  Program %d %s\n", program->id,
                   name ? name->value : "");
            dump_metadata(NULL, program->metadata, "    ");
            for (k = 0; k < program->nb_stream_indexes; k++) {
                dump_stream_format(ic, program->stream_index[k],
                                   index, is_output);
                printed[program->stream_index[k]] = 1;
            }
            total += program->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);
}
相关推荐
cuijiecheng20186 小时前
音视频入门基础:FLV专题(13)——FFmpeg源码中,解析任意Type值的SCRIPTDATAVALUE类型的实现
ffmpeg·音视频
小神.Chen1 天前
YouTube音视频合并批处理基于 FFmpeg的
ffmpeg·音视频
昱禹3 天前
记一次因视频编码无法在浏览器播放、编码视频报错问题
linux·python·opencv·ffmpeg·音视频
寻找09之夏3 天前
【FFmpeg 深度解析】:全方位视频合成
ffmpeg·音视频
zanglengyu3 天前
ffmpeg取rtsp流音频数据保存声音为wav文件
ffmpeg·音视频
cuijiecheng20183 天前
音视频入门基础:FLV专题(11)——FFmpeg源码中,解析SCRIPTDATASTRING类型的ScriptDataValue的实现
ffmpeg·音视频
汪子熙3 天前
什么是 LDAC、SBC 和 AAC 音频编码技术
ffmpeg·音视频·aac
cpp_learners3 天前
Windows环境 源码编译 FFmpeg
windows·ffmpeg·源码编译·ffmpeg源码编译
cuijiecheng20184 天前
音视频入门基础:FLV专题(8)——FFmpeg源码中,解码Tag header的实现
ffmpeg·音视频
职场人参4 天前
如何改变音频声音大小?关于改变音频大小的方法介绍
android·ffmpeg