iOS — 全景视频360元素注入

基于Bento4库,对MP4的视频注入360元素,使得MP4的视频,变成360全景视频。

Bento4官网地址:https://www.bento4.com

Bento4的git地址:https://github.com/axiomatic-systems/Bento4

clone 代码后,可在项目中,查看Readme文档,可以使用cmake 指令操作,也可以用mac xcode的。

由于有Xcode,所以我这里,直接用xcode的编译

目录:Bento4-master/Build/Targets/universal-apple-macosx/Bento4.xcodeproj ,

点击打开Bento4.xcodeproj 

Scheme,选择Bento4,然后在Build Phases的Headers中,把Project的头文件,放到Public,最后编译,获得lib + include。

把CApi 和Runtime 中需要的文件,拖拽进来。

iOS --- 全景视频360元素注入

然后新建一个NSObject类型MaBento4Tool,把.m 改成 .mm 变成C++的类

在.h 定义函数:

+ (BOOL)inject360MetadataFromInputMP4:(NSString *)inputPath

                              outputMP4:(NSString*)outputPath;

在.mm 中实现:

#import”Ap4.h”

#import “Ap4UuidAtom.h”

#include “Ap4FileByteStream.h”

+ (BOOL)inject360MetadataFromInputMP4:(NSString *)inputPath{

                              outputMP4:(NSString*)outputPath{

    // ———- 1. 加载 JSON 数据 ———-

    NSDictionary*sphericalMeta =@{

        @”Spherical”:@YES,

        @”Stitched”:@YES,

        @”StereoMode”:@”mono”,

        @”projection”: @”equirectangular”,

        @”SourceCount”: @(1),

        @”side_data_type”: @”Spherical Mappin”,

        @”initial_view_orientation”: @{

                @”yaw”:@0,

                @”pitch”:@0,

                @”roll”:@0

        }

    };

    NSDictionary*dict =@{@”side_data_list”:sphericalMeta};

    NSError*error =nil;

    NSData*jsonData = [NSJSONSerializationdataWithJSONObject:dictoptions:0error:&error];

    if(!jsonData || error) {

        NSLog(@”❌ JSON 构建失败: %@”, error);

        returnNO;

    }

    // ———- 2. 创建读写 ByteStream ———-

    AP4_ByteStream* input =nullptr;

    AP4_ByteStream* output =nullptr;

    // 打开输入 MP4(用于读)

    AP4_Resultresult =AP4_FileByteStream::Create([inputPathUTF8String],AP4_FileByteStream::STREAM_MODE_READ, input);

    if(AP4_FAILED(result) || !input) {

        NSLog(@”❌ 无法打开输入 MP4″);

        returnNO;

    }

    // 打开输出 MP4(用于写)

    result =AP4_FileByteStream::Create([outputPathUTF8String],AP4_FileByteStream::STREAM_MODE_WRITE, output);

    if(AP4_FAILED(result) || !output) {

        input->Release();

        NSLog(@”❌ 无法打开输出 MP4″);

        returnNO;

    }

    // ———- 3. 加载 MP4 文件结构 ———-

    AP4_Filemp4File(*input);

    AP4_Movie* movie = mp4File.GetMovie();

    if(!movie) {

        NSLog(@”❌ 无法读取 MP4 movie 对象”);

        input->Release();

        output->Release();

        returnNO;

    }

    // ———- 4. 注入 JSON(Google Spherical Video V2)到 sample description ———-

    AP4_List::Item* trackItem = movie->GetTracks().FirstItem();

    while(trackItem) {

        AP4_Track* track = trackItem->GetData();

        if(track && track->GetType() ==AP4_Track::TYPE_VIDEO) {

            if(track) {

                constAP4_UI08v1_uuid[] = {

                    0xFF,0xCC,0x82,0x63,

                    0xF8,0x55,

                    0x4A,0x93,

                    0x88,0x14,

                    0x58,0x7A,0x02,0x52,0x1F,0xDD

                };

                constchar* sphericalXml =

                    “”

                    “

                    ” xmlns:GSpherical=”http://ns.google.com/videos/1.0/spherical/”>”

                    “true”

                    “true”

                   “mono”

                    “Spherical Metadata Tool”

                    “equirectangular”

                    “”;

                AP4_DataBufferuuidPayload((constAP4_Byte*)sphericalXml, (AP4_Size)strlen(sphericalXml));

                // 创建内存字节流

                AP4_MemoryByteStream* memStream = new AP4_MemoryByteStream(

                    (constAP4_UI08*)sphericalXml,

                    (AP4_Size)strlen(sphericalXml)

                );

                // 创建 UUID box

                AP4_UnknownUuidAtom* uuidAtom = new AP4_UnknownUuidAtom(

                    (AP4_UI64)strlen(sphericalXml),

                    v1_uuid,

                    *memStream

                );

                constAP4_Atom* trakAtomConst = track->GetTrakAtom();

                AP4_ContainerAtom* trakAtom =dynamic_cast((AP4_Atom*)trakAtomConst);

                if(trakAtom) {

                    trakAtom->AddChild(uuidAtom);

                    NSLog(@”✅ 注入 Google Spherical V1 (XML)”);

                }else{

                    NSLog(@”❌ trakAtom 无法转换为 Container 类型”);

                }

                break;

            }

        }

        trackItem = trackItem->GetNext();

    }

    // ———- 6. 保存文件 ———-

    AP4_FileWriter::Write(mp4File, *output);

    input->Release();

    output->Release();

    NSLog(@”✅ 360 Metadata 注入成功!”);

    return YES;

}

然后在项目中,就可以开心调用;

 [MaBento4Tool inject360MetadataFromInputMP4:“输入的视频地址” outputMP4:”输出的视频地址”];

查看视频信息指令:(需要在终端中安装ffmpeg,后再执行)

ffprobe -v quiet -print_format json -show_format -show_streams “视频地址”

如果有看到如下信息, 祝贺你,你已经成功注入360全景视频元素

 “side_data_list”: [

                {

                    “side_data_type”: “Spherical Mapping”,

                    “projection”: “equirectangular”,

                    “yaw”: 0,

                    “pitch”: 0,

                    “roll”: 0

                }

            ]

之前踩过的坑

1)通过生成一秒的360模版视频A,然后通过ffmpeg,把视频A的元素取出赋值到 视频B中,通过查看视频信息,未查找相关信息

2)GPAC的库,通过相关编译,集成后,还是各种报错

如果有时间,你们也可以尝试以上两点,是否能走通,麻烦告知。

© 版权声明

相关文章

暂无评论

none
暂无评论...