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 中需要的文件,拖拽进来。

然后新建一个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的库,通过相关编译,集成后,还是各种报错

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,983评论 6 537
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,772评论 3 422
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,947评论 0 381
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,201评论 1 315
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,960评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,350评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,406评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,549评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,104评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,914评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,089评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,647评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,340评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,753评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,007评论 1 289
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,834评论 3 395
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,106评论 2 375

推荐阅读更多精彩内容