Coder Social home page Coder Social logo

poholo / mcplayerkit Goto Github PK

View Code? Open in Web Editor NEW
40.0 2.0 7.0 7.71 MB

MCPlayerKit is iOS Player, PlayerCoreType: AVPlayer can use play some video, IJKPlayer type can play video, Live ...

License: MIT License

Objective-C 95.68% Ruby 0.76% Swift 3.55%
cocoapods ijkplayer avplayer playerkit video playerview mcstyle

mcplayerkit's Introduction

MCPlayerKit

MCPlayerKit 介绍

从事移动端开发以来,一直在做音视频类的开发,苹果的播放器基本定制型太强,需要定制在开源有kxmovie,授权的vitamio等,但层次不一,经过几年的发展,尤其是在这两年直播等投资热的趋势下,音视频技术逐渐趋于成熟,随便找几个库就能解决燃眉之急,开源的力量更进一步的推进了技术的发展,我也想写个简单的项目,写出一些心得。

MCPlayerKit 是基于AVPlayer和IJKPlayer做的一款播放内核播放模块,做IJKPlayer支持是因为AVPlayer对于一些格式协议的支持的补充,比如flv、RTMP等。 [MCPlayerKit/GeneralPlayerUI]是一套基于MCPlayerKit高度封装16:9模式的播放UI,可以通过MCStyle样式完全自定图标、部分custom区域等。

update

-   pod  install --repo-update --verbose 支持2021devices 
0.2.3 fix swift cocoapods use_frameworks 集成报错问题(swift使用例子参照./ExampleSwift)

特点

MCPlayerKit
- PlayerKit高度抽象出播放层和渲染层
- 耦合低,使用方便
- support IJK & AVPlayer

GeneralPlayerUI
- 旋转
- support 2018 Devices
- loading
- 播放中断重试
- 用户可以自定义UI颜色、样式、字体大小
- 自定义topRightView

Installation

Installation with CocoaPods

To integrate MCPlayerKit into your Xcode project using CocoaPods, specify it in your Podfile: 如果纯使用MCPlayerKit播放功能,请用

pod 'MCPlayerKit/Core' or pod 'MCPlayerKit'

如果需要使用高度通用UI的,可以用

pod 'MCPlayerKit/GeneralPlayerUI'

GeneralPlayerUI 样式依赖于'MCStyle',Example/Classes/Modules/GeneralPlayer/MCPlayerGeneralController有他的详细使用,
你可以通过json配置GeneralPlayerUI颜色、样式、字体等。

Run pod install

0.2.3 已经解决swift cocoapods use_framework报错问题

使用方法

1. 纯播放功能,自定义UI

1.1 功能

    a. support AVPlayer & IJKPlayer
    b. 统一渲染页面

1.2 接入代码

- (MCPlayerKit *)playerKit {
    if (!_playerKit) {
        _playerKit = [[MCPlayerKit alloc] initWithPlayerView:self.playerView];
        _playerKit.playerCoreType = MCPlayerCoreAVPlayer;
        _playerKit.playerStatusDelegate = self;
    }
    return _playerKit;
}

//自定义渲染界面
- (MCPlayerView *)playerView {
    if (!_playerView) {
        CGFloat width = MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
        CGFloat height = width * 9 / 16.0f;
        _playerView = [[MCPlayerView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
    }
    return _playerView;
}
[self.playerKit playUrls:@[@"http://aliuwmp3.changba.com/userdata/video/45F6BD5E445E4C029C33DC5901307461.mp4"]];

2.GeneralPlayerUI 通用播放器UI

2.1 功能

    a. 旋转
    b. support 2018 Devices
    c. loading
    b. 播放中断重试
    c. 用户可以自定义UI颜色、样式、字体大小
    e. 自定义topRightView
    f. 支持UI 是否能seek状态、Live状态
TODO:
    I. 投屏UI

2.2 接入代码

    //颜色配置
    [MCStyleManager share].colorStyleDataCallback = ^NSDictionary *(void) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"CustomPlayerColor" ofType:@"json"];
        NSError *error;
        NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:&error];
        NSAssert(!error, @"read json file error");
        return dictionary[@"data"];
    };

    //字体样式配置
    [MCStyleManager share].fontStyleDataCallBack = ^NSDictionary *(void) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"CustomPlayerFont" ofType:@"json"];
        NSError *error;
        NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:&error];
        NSAssert(!error, @"read json file error");
        return dictionary[@"data"];
    };

    //图片等配置
    [MCStyleManager share].styleDataCallback = ^NSDictionary *(void) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"CustomPlayerStyle" ofType:@"json"];
        NSError *error;
        NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:&error];
        NSAssert(!error, @"read json file error");
        return dictionary[@"data"];
    };
    [[MCStyleManager share] loadData];

    [self.view addSubview:self.playerView];
    [self.playerView updatePlayerPicture:@"https://avatars0.githubusercontent.com/u/3861387?s=460&v=4"];
    [self.playerView updateTitle:@"Skipping code signing because the target does not have an Info.plist file. (in target 'App')"];
//    [self.playerKit playUrls:@[@"http://aliuwmp3.changba.com/userdata/video/45F6BD5E445E4C029C33DC5901307461.mp4"]];
    [self.playerKit playUrls:@[@"http://aaaaaliuwmp3.changba.com/userdata/video/45F6BD5E445E4C029C33DC5901307461.mp4"]];
    [self.playerView updateAction:self.playerKit];
    self.playerView.retryPlayUrl = ^NSString *(void) {
        return @"http://aliuwmp3.changba.com/userdata/video/45F6BD5E445E4C029C33DC5901307461.mp4";
    };
    
    - (MCPlayerKit *)playerKit {
        if (!_playerKit) {
            _playerKit = [[MCPlayerKit alloc] initWithPlayerView:self.playerView.playerView];
            _playerKit.playerCoreType = MCPlayerCoreAVPlayer;
        }
        return _playerKit;
    }
    
    - (MCPlayerGeneralView *)playerView {
        if (!_playerView) {
            CGFloat width = MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
            CGFloat height = width * 9 / 16.0f + [MCDeviceUtils xTop];
            _playerView = [[MCPlayerGeneralView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
        }
        return _playerView;
    }
    
    具体参照 Example/Classes/Modules/GeneralPlayer/MCPlayerGeneralController

2.2.0 style

使用参照 MCStyle

播放页样式颜色
{
  "success": true,
  "data": {
    "player_title_color": "#ffffff",
    "player_time_color": "#ffffff",
    "player_progress_color": "#5cc0f2",
    "player_progress_buffer_trackcolor": "#97a2a8",
    "player_progress_buffer_color": "#737b80",
    "player_circle_progress_track_color": "#ffffff",
    "player_terminal_bgcolor": "#edf1f5",
    "player_terminal_titlecolor": "#999999",
    "player_terminal_mentioncolor": "#666666",
    "player_terminal_mentioncolor_alert": "#76bdff"
  }
}

播放器字体

{
  "success": true,
  "data": {
    "player_title_font": 12,
    "player_time_font": 10,
    "player_terminal_title_font": 15,
    "player_terminal_info_font": 13
  }
}

播放器图片参数等

{
  "data": {
    "player_contentInsetII": "{8, 8, 8, 8}",
    "player_contentInsetIII": "{4, 4, 4, 4}",
    "player_terminal_inset": "{15, 15, 15, 15}",
    "player_header_0": "player_header_0",
    "player_header_1": "player_header_1",
    "player_header_1_s": "player_header_1_s",
    "player_body_0": "player_body_0",
    "player_body_0_s": "player_body_0_s",
    "player_body_1": "player_body_1",
    "player_body_1_s": "player_body_1_s",
    "player_footer_0": "player_footer_0",
    "player_footer_0_s": "player_footer_0_s",
    "player_footer_1": "player_footer_1",
    "player_footer_1_s": "player_footer_1_s",
    "player_control_0": "player_control_0",
    "player_control_1": "player_control_1",
    "player_control_2": "player_control_2",
    "player_loading_default": "player_loading_pic",
    "player_slider": "player_slider",
    "player_terminal_title_is_image": 1,
    "player_terminal_bg": "player_terminal_bg",
    "player_terminal_bg_alpha": 0.3,
    "player_terminal_title_image": "player_terminal_title_image"
  }
}

2.2.1 自定义播放器headerView右侧view

{
        MCPlayerCommonButton *btn = [MCPlayerCommonButton new];
        [btn setTitle:@"清晰度1" forState:UIControlStateNormal];
        [btn setBackgroundColor:[UIColor orangeColor]];
        btn.size = CGSizeMake(60, 30);
        btn.tag = 99;
        [self.playerView.topView.rightView addCustom:btn];
        btn.titleLabel.font = [UIFont systemFontOfSize:12];
    }
    具体参照MCPlayerCommonButton.h 注释

2.2.2 释放问题

self.playerView.outEventCallBack = ^id(NSString *action, id value) {
    __strong typeof(weakSelf) strongSelf = weakSelf;
    if([action isEqualToString:kMCPlayerDestory]) {
        [strongSelf destory];
    }
    return nil;
};

- (void)destory {
    if(_playerView) {
        [_playerView removeFromSuperview];
        _playerView = nil;
    }
    if(_playerKit) {
        [_playerKit destory];
        _playerKit = nil;
    }
}

2.3 Screenshot

MCPlayerKit_GeneralPlayerUI

类结构

PlayerKit --------------- 播放器核心,AVPlayer与IJKPlayer抽象
    -- Core               Player抽象与实现以及PlayerKit播放器控制
    -- Extend             辅助类
    -- PlayerView         播放器界面父类,Custom播放器界面View必须继承与此类
    
GeneralPlayerUI----------- 通用播放组件UI
    -- Views               通用UI subviews
    -- MCPlayerGeneralView 通用播放界面

Commen ------------------- 通用类

more

此项目会作为长期维护项目,接受各位指导。

support

Tanks JetBrains AppCode Download JetBrains Develop Tools

License

These PlayerKit are available under the MIT license.

mcplayerkit's People

Contributors

imgbotapp avatar majiancheng avatar poholo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

mcplayerkit's Issues

为什么运行时报错:“PlayerKitDemo.app” couldn’t be opened because you don’t have permission to view it

真机 编译可以通过,但一旦运行 就 报错如下:

The file “PlayerKitDemo.app” couldn’t be opened because you don’t have permission to view it.
Domain: NSCocoaErrorDomain
Code: 257
Failure Reason: You don’t have permission.
Recovery Suggestion: To view or change permissions, select the item in the Finder and choose File > Get Info.
User Info: {
NSFilePath = "/Users/leebeen/Library/Developer/Xcode/DerivedData/PlayerKitDemo-hivdczixikqipffrhxhcwhkfruzb/Build/Products/Debug-iphoneos/PlayerKitDemo.app";
}

The operation couldn’t be completed. Permission denied
Domain: NSPOSIXErrorDomain
Code: 13
Failure Reason: Permission denied

System Information

macOS Version 10.15.7 (Build 19H114)
Xcode 12.4 (17801) (Build 12D4e)
Timestamp: 2021-08-29T11:41:30+08:00

关于ijk中IJKSDLGLView.m文件的线程问题

我是在ijk的仓库看到你的提交,想请教下关于这个文件的线程问题。ijk里的文件比对差异太多了,可能有看漏的。

1、在IJKSDLGLView.m中的-invalidateRenderBuffer 方法,在调用 [self display:nil]; 之前,还是应该加上

if (_isRenderBufferInvalidated)
     [self display:nil];

判断,不然会概率性的崩在下面这句:

if (!IJK_GLES2_Renderer_renderOverlay(_renderer, overlay))
        ALOGE("[EGL] IJK_GLES2_render failed\n");

2、第一次进入还是会卡,-displayInternal: 这个方法中的

[[self eaglLayer] setContentsScale:_scaleFactor];

[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

我都用dispatch_async(dispatch_get_main_queue(), ^{ });包起来了。你的修改似乎没动这里,请问是怎么做的?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.