66 lines
2.6 KiB
Plaintext
66 lines
2.6 KiB
Plaintext
//
|
|
// FFmpegKitIOS.mm
|
|
// iOS 端 .264 -> .mp4 转码桥(extern "C"),供 C# 经 [DllImport("__Internal")] 调用。
|
|
//
|
|
// 原理: 调用 native ffmpeg-kit(ffmpegkit.framework)的 executeWithArguments,用 libx264
|
|
// 重编码重新生成干净的 SPS/PPS + 时间戳,修复设备(OPPO/MTK 等)产出裸流坏 PPS 导致的
|
|
// 解码卡死("non-existing PPS 0 referenced")。
|
|
//
|
|
// 依赖: 需将 ffmpeg-kit iOS full-gpl 的 .xcframework(含 ffmpegkit.framework)放进
|
|
// Assets/Plugins/iOS/FFmpegKit/(Unity 会在构建 Xcode 工程时自动链接)。
|
|
// 版本需与本项目 Android 端一致: dev.ffmpegkit-maintained:ffmpeg-kit-full-gpl:6.0.3
|
|
// (FFmpeg n6.1.6,含 libx264)。缺少该 framework 时本文件编译期即报错找不到头文件,属预期。
|
|
//
|
|
#import <ffmpegkit/FFmpegKit.h>
|
|
#import <ffmpegkit/FFmpegKitConfig.h>
|
|
#import <Foundation/Foundation.h>
|
|
#import <signal.h>
|
|
|
|
static BOOL ffmpegKitConfigured = NO;
|
|
|
|
// 一次性配置:忽略 Unity/IL2CPP 运行时可能被 ffmpeg-kit 信号处理干扰的信号
|
|
static void FFmpegKitConfigureOnce(void) {
|
|
if (ffmpegKitConfigured) return;
|
|
ffmpegKitConfigured = YES;
|
|
// 强转成 ffmpeg-kit 的 Signal 枚举(数值与 <signal.h> 系统信号常量一致)
|
|
[FFmpegKitConfig ignoreSignal:(Signal)SIGXCPU];
|
|
[FFmpegKitConfig ignoreSignal:(Signal)SIGPIPE];
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
/// 执行 ffmpeg 转码。
|
|
/// @param argv 参数数组(C# string[] 会作为 UTF-8 char** 传入)
|
|
/// @param argc 参数个数
|
|
/// @return 0=成功;否则为 ffmpeg 退出码;-1=参数或内部错误
|
|
int FFmpegKitExecuteWithArguments(char **argv, int argc) {
|
|
@autoreleasepool {
|
|
FFmpegKitConfigureOnce();
|
|
|
|
if (argv == NULL || argc <= 0) {
|
|
NSLog(@"[FFmpegKitIOS] bad args argv=%p argc=%d", argv, argc);
|
|
return -1;
|
|
}
|
|
|
|
NSMutableArray *arguments = [NSMutableArray arrayWithCapacity:(NSUInteger)argc];
|
|
for (int i = 0; i < argc; i++) {
|
|
if (argv[i] == NULL) continue;
|
|
[arguments addObject:[NSString stringWithUTF8String:argv[i]]];
|
|
}
|
|
|
|
NSLog(@"[FFmpegKitIOS] execute: %@", [arguments componentsJoinedByString:@" "]);
|
|
|
|
FFmpegSession *session = [FFmpegKit executeWithArguments:arguments];
|
|
ReturnCode *returnCode = [session getReturnCode];
|
|
|
|
if ([ReturnCode isSuccess:returnCode]) {
|
|
return 0;
|
|
}
|
|
if (returnCode == nil) {
|
|
NSLog(@"[FFmpegKitIOS] returnCode nil, treat as failure.");
|
|
return -1;
|
|
}
|
|
return (int)[returnCode getValue];
|
|
}
|
|
}
|
|
} |