iOS集成FFmpeg命令行

前言

本文是继iOS编译FFmpeg的第二部分

集成到工程

找到对应文件

将Appdelegate.m后缀改为.mm,开启混编模式。command+B,如果没有报错,则表明编译成功。

在ffmpeg中找到fftools

在scratch中找到config

到iOS工程中

解决集成报错(4.2.3版本)

增加库

ffmpeg.h注释

#include "libavutil/thread.h"

ffmpeg_fliter.c注释

#include "libavresample/avresample.h"

cmdutils.c注释

#include "compat/va_copy.h"
#include "libavresample/avresample.h"
#include "libpostproc/postprocess.h"
#include "libavutil/libm.h"
#include "libavformat/network.h"

PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
PRINT_LIB_INFO(postproc,   POSTPROC,   flags, level);

ffmpeg.c注释

include "libavutil/internal.h"
#include "libavutil/libm.h"
#include "libavutil/thread.h"
#include "libavcodec/mathops.h"
#include "libavformat/os_support.h"

nb0_frames = nb_frames = mid_pred(ost->last_nb0_frames[0],
                                          ost->last_nb0_frames[1],
                                          ost->last_nb0_frames[2]);
                                          
ff_dlog(NULL, "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n",
                    ost->forced_keyframes_expr_const_values[FKF_N],
                    ost->forced_keyframes_expr_const_values[FKF_N_FORCED],
                    ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N],
                    ost->forced_keyframes_expr_const_values[FKF_T],
                    ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T],
                    res);

ffmpeg.c头部导入

#include "pthread.h"

ffmpeg.h添加

int ffmpeg_main(int argc, char **argv);

将ffmpeg.c中的main改为ffmpeg_main

优化集成后的问题

计数器置零问题 (ffmpeg.c的代码中会访问空属性导致程序崩溃)

找到ffmpeg.c中的ffmpeg_cleanup函数改成如下

nb_filtergraphs=0;
nb_output_files=0;
nb_output_streams=0;
nb_input_files=0;
nb_input_streams=0;

命令执行结束崩溃问题
第一种方法(推荐)

  • FFmpeg 默认执行完会执行exit_program方法结束进程,而iOS下只能启动一个进程,如果默认不做处理,执行完一条命令后app就自动退出了,所以需要处理下。
  • ffmpeg.cffmpeg_main函数中,把所有调用exit_program函数 ,改为调用ffmpeg_cleanup函数就可以了。到这一步就可以使用FFmpeg给我们提供的命令啦(〃'▽'〃)

第二种方法

  • 此方法需要2个文件

cmdutils.c中的exit_program函数改成如下

void exit_program(int ret)
{
    if (program_exit)
        program_exit(ret);

    //标记为转换完成
    stopRuning();
//这个是结束进程的方法,让ffmpeg进行完转码以后不至于退出程序
//    exit(ret);
//    所以将退出进程的方法改造为退出线程
    pthread_exit(NULL);
}

运行

编写OC调用

#import "FFmpegTools.h"
#import "ffmpeg.h"

@implementation FFmpegTools

///执行ffmpeg指令," "为分割标记符
+ (void)runCmd:(NSString *)commandStr completionBlock:(void(^)(int result))completionBlock {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 根据 " " 将指令分割为指令数组
        NSArray *argv_array = [commandStr componentsSeparatedByString:(@" ")];
        // 将OC对象转换为对应的C对象
        int argc = (int)argv_array.count;
        char** argv = (char**)malloc(sizeof(char*)*argc);
        for(int i=0; i < argc; i++) {
            argv[i] = (char*)malloc(sizeof(char)*1024);
            strcpy(argv[i],[[argv_array objectAtIndex:i] UTF8String]);
        }
        
//        ffmpeg_main
        // 传入指令数及指令数组,result==0表示成功
        int result = ffmpeg_main(argc,argv);
        NSLog(@"执行FFmpeg命令:%@,result = %d",commandStr,result);
        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(result);
        });
    });
}

@end

运行代码

 NSString *inputPath = [[NSBundle mainBundle] pathForResource:@"123.ts" ofType:nil];
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *outputPath = [docDir stringByAppendingPathComponent:@"videoConver2.mov"];
    NSString *commandStr = [NSString stringWithFormat:@"ffmpeg -i %@ -b:v 2000K -y %@", inputPath, outputPath];
    NSLog(@"执行1");
    [FFmpegTools runCmd:commandStr completionBlock:^(int result) {
        // 0表示成功
        NSLog(@"结果%d",result);
    }];
    NSLog(@"执行2");

原文 iOS集成FFmpeg命令行 - 掘金

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

猜你喜欢

转载自blog.csdn.net/yinshipin007/article/details/131744401