美文网首页
iOS ijkplayer无法旋转带有rotation信息的视频

iOS ijkplayer无法旋转带有rotation信息的视频

作者: YannChee | 来源:发表于2021-11-11 10:16 被阅读0次

在网上搜了一下,基本上搜出来都是安卓这方面的问题,iOS的极少,但是搜了一下github的issue发现大部分都是iOS的提问;

安卓的解决办法是:

  • 修改ijkmedia/ijkplayer/config.h文件,开启 CONFIG_AVFILTER
  • 或者是 开启mediacodec-auto-rotate 这个option选项

我都一一试过了,iOS都没有效果; 但是安卓确实是没有问题的;
看来ijkplayer官方对iOS版本的支持没有安卓端的好

目前iOS方面比较好的解决办法是,使用AVAsset 去获取视频元数据信息的旋转信息,然后在播放器size改变的回调里面手动旋转播放器的视图

这种方法虽然可以解决问题,但是并不是最佳解决办法;

由于ijkplayer 既没有处理视频元数据旋转信息,也没有对外暴露视频的旋转信息;但是底层的FFMPEG (ff_ffplayer)本来就支持上面功能的

所以最佳解决办法是修修改ijkplayer 源码,暴露旋转信息角度信息或者是让它调用ff_ffplayer 相关方法支持带有旋转角度的视频

下面是我的项目代码,临时的解决方案

- (void)setAssetURL:(NSURL *)assetURL {
    //先获取视频地址的旋转方向
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.rotationNumber = [self degressFromVideoFileWithURL:assetURL];
    });
    self.isRotatedPlayerView = NO;
    [super setAssetURL:assetURL];
}

// 旋转播放器的view
- (void)rotatePlayerViewIfNeed {
    if (self.rotationNumber <= 0 || self.isRotatedPlayerView) {
        return;
    }
    
    UIView *targetView = self.currentPlayerManager.view;
    // 先复原
    targetView.transform = CGAffineTransformIdentity;
    
    //判断旋转角度
    if (self.rotationNumber == 90) {
        targetView.transform = CGAffineTransformMakeRotation(M_PI_2);
        CGSize newVideoSize = CGSizeMake(self.presentationSize.height, self.presentationSize.width);
        targetView.frame =  [self calculatePlayerViewFrameWithPlayerFrame:self.frame videoSize:newVideoSize];
        self.isRotatedPlayerView = YES;
        return;
    }
    
    //判断旋转角度
    if (self.rotationNumber == 180) {
        targetView.transform = CGAffineTransformMakeRotation(M_PI);
        targetView.frame =  [self calculatePlayerViewFrameWithPlayerFrame:self.frame videoSize:self.presentationSize];
        self.isRotatedPlayerView = YES;
        return;
    }
    
    //判断旋转角度
    if (self.rotationNumber == 270) {
        targetView.transform = CGAffineTransformMakeRotation(3 * M_PI_2);
        CGSize newVideoSize = CGSizeMake(self.presentationSize.height, self.presentationSize.width);
        targetView.frame =  [self calculatePlayerViewFrameWithPlayerFrame:self.frame videoSize:newVideoSize];
        self.isRotatedPlayerView = YES;
        return;
    }
}

// 获取视频URL的旋转方向
- (NSUInteger)degressFromVideoFileWithURL:(NSURL *)url {
    NSUInteger degress = 0;
    
    AVAsset *asset = [AVAsset assetWithURL:url];
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    if([tracks count] > 0) {
        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
        CGAffineTransform t = videoTrack.preferredTransform;
        if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
            // Portrait
            degress = 90;
        }else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
            // PortraitUpsideDown
            degress = 270;
        }else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
            // LandscapeRight
            degress = 0;
        }else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
            // LandscapeLeft
            degress = 180;
        }
    }
    
    return degress;
}



/**< 根据播放器frame 和视频size 动态计算播放器view的最佳frame */
- (CGRect)calculatePlayerViewFrameWithPlayerFrame:(CGRect)playerFrame videoSize:(CGSize)videoSize {
    
    CGFloat min_x = 0;
    CGFloat min_y = 0;
    CGFloat min_w = 0;
    CGFloat min_h = 0;
    CGFloat min_view_w = playerFrame.size.width;
    CGFloat min_view_h = playerFrame.size.height;
    
    CGSize playerViewSize = CGSizeZero;
    CGFloat videoWidth = videoSize.width;
    CGFloat videoHeight = videoSize.height;
    
    if (videoHeight == 0 || min_view_h == 0) {
        return self.frame;
    }
    
    CGFloat screenScale = min_view_w / min_view_h;
    CGFloat videoScale = videoWidth/videoHeight;
    if (screenScale > videoScale) {
        CGFloat height = min_view_h;
        CGFloat width = height * videoScale;
        playerViewSize = CGSizeMake(width, height);
    } else {
        CGFloat width = min_view_w;
        CGFloat height = width / videoScale;
        playerViewSize = CGSizeMake(width, height);
    }
    
    if (self.scalingMode == FPPlayerScalingModeAspectFit || self.scalingMode == FPPlayerScalingModeAspectFit) {
        min_w = playerViewSize.width;
        min_h = playerViewSize.height;
        min_x = (min_view_w - min_w) * 0.5;
        min_y = (min_view_h - min_h) * 0.5;
        return CGRectMake(min_x, min_y, min_w, min_h);;
    } else if (self.scalingMode == FPPlayerScalingModeAspectFill || self.scalingMode == FPPlayerScalingModeFill) {
        return self.frame;
    }
    return self.frame;
}
 // 播放状态随时可播放
    self.player.playerReadyToPlay = ^(id<FPPlayerMediaPlayback>  _Nonnull asset, NSURL * _Nonnull assetURL) {
        @strongify(self);
        self.loadingView.hidden = YES;
        [self.player rotatePlayerViewIfNeed];
    };
    
    // 视频尺寸变换
    self.player.presentationSizeChanged = ^(id<FPPlayerMediaPlayback>  _Nonnull asset, CGSize size) {
        @strongify(self);
        [self.player rotatePlayerViewIfNeed];
    };
    

相关文章

网友评论

      本文标题:iOS ijkplayer无法旋转带有rotation信息的视频

      本文链接:https://www.haomeiwen.com/subject/yjmwzltx.html