Android 는 Unity3D 에서 RTMP 를 푸 시 하 는 예 를 실현 합 니 다.

화면 채집 에 관 한 두 가지 방안 이 있 습 니 다.
1.안 드 로 이 드 네 이 티 브 화면 수집 프로젝트 를 직접 밀봉 하고 유 니 티 에서 인 터 페 이 스 를 제공 하 며 화면 권한 을 받 은 후 화면 데 이 터 를 가 져 와 푸 시 합 니 다.
2.유 니 티 의 창 이나 카메라 데이터 만 가 져 오 면 유 니 티 에서 푸 시 할 원본 데 이 터 를 얻 은 다음 에 네 이 티 브 RTMP 푸 시 인 터 페 이 스 를 패키지 하고 네 이 티 브 SDK 를 호출 하여 데 이 터 를 푸 시 할 수 있 습 니 다.이런 방법 은 수집 해 야 할 데이터 내용 을 사용자 정의 할 수 있 고 네 이 티 브 SDK 가 제공 하 는 인터페이스 에 따라 데이터 도 킹 을 완성 하면 됩 니 다.구체 적 으로 본문 을 참조 하 다.
본 고 는 안 드 로 이 드 플랫폼 의 경우 Unity 환경 에서 의 안 드 로 이 드 플랫폼 RTMP 추 류 를 소개 한다.데이터 수집 은 Unity 에서 이 루어 지고 데이터 인 코딩 푸 시 는 황소 생방송 SDK(공식)안 드 로 이 드 플랫폼 RTMP 생방송 푸 시 SDK 네 이 티 브 라 이브 러 리 가 대외 2 차 로 포 장 된 인 터 페 이 스 를 호출 하여 효율 적 으로 RTMP 푸 시 를 실현 한다.쓸데없는 말 을 많이 하고,먼저 위의 그림 에서 효 과 를 보다.
다음 그림 은 안 드 로 이 드 플랫폼 유 니 티 환경 에서 화면 을 채집 하고 인 코딩 을 RTMP 서버 로 보 낸 다음 에 윈도 플랫폼 재생 기 는 RTMP 스 트림 을 끌 어 와 재생 합 니 다.지연 효 과 를 쉽게 볼 수 있 도록 안 드 로 이 드 엔 드 의 유 니 티 창 에 현재 시간 을 표시 합 니 다.전체 지연 은 밀리초 단위 입 니 다.

데이터 수집 푸 시
유 니 티 데이터 수집 은 상대 적 으로 간단 하여 RGB 24 의 데 이 터 를 쉽게 얻 을 수 있 습 니 다.

texture_ = new Texture2D(video_width_, video_height_, TextureFormat.RGB24, false);

texture_.ReadPixels(new Rect(0, 0, video_width_, video_height_), 0, 0, false);

texture_.Apply();
  
그리고 texture 를 호출 합 니 다.GetRawTextureData(); 데 이 터 를 가 져 오 면 됩 니 다.
데 이 터 를 받 은 후,네 이 티 브 SDK 로 포 장 된 NT 를 호출 합 니 다.PB_U3D_OnCapture VideoRGB24PtrData()인터페이스 로 데이터 배달 이 완료 되 었 습 니 다.
단순 호출 프로 세 스

    private void Start()
    {
        game_object_ = this.gameObject.name;

        AndroidJavaClass android_class = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        java_obj_cur_activity_ = android_class.GetStatic<AndroidJavaObject>("currentActivity");
        pusher_obj_ = new AndroidJavaObject("com.daniulive.smartpublisher.SmartPublisherUnity3d");

        NT_PB_U3D_Init();

        //NT_U3D_SetSDKClientKey("", "", 0);

        btn_encode_mode_.onClick.AddListener(OnEncodeModeBtnClicked);

        btn_pusher_.onClick.AddListener(OnPusherBtnClicked);

        btn_mute_.onClick.AddListener(OnMuteBtnClicked);
    }
인터페이스 초기 화 완료 후 Push()인터페이스 호출

    public void Push()
    {
        if (is_running)
        {
            Debug.Log("   ..");   
            return;
        }

        if (texture_ != null)
        {
            UnityEngine.Object.Destroy(texture_);
            texture_ = null;
        }

        video_width_ = Screen.width;
        video_height_ = Screen.height;

        scale_width_ = (video_width_ + 1) / 2;
        scale_height_ = (video_height_ + 1) / 2;

        if (scale_width_ % 2 != 0)
        {
            scale_width_ = scale_width_ + 1;
        }

        if (scale_height_ % 2 != 0)
        {
            scale_height_ = scale_height_ + 1;
        }

        texture_ = new Texture2D(video_width_, video_height_, TextureFormat.RGB24, false);

        //      url
        string url = input_url_.text.Trim();

        if (!url.StartsWith("rtmp://"))
        {
            push_url_ = "rtmp://192.168.0.199:1935/hls/stream1";
        }
        else
        {
            push_url_ = url;
        }

        OpenPusher();

        if (pusher_handle_ == 0)
            return;

        NT_PB_U3D_Set_Game_Object(pusher_handle_, game_object_);

        /* ++              ++ */

        InitAndSetConfig();

        NT_PB_U3D_SetPushUrl(pusher_handle_, push_url_);
        /* --              -- */

        int flag = NT_PB_U3D_StartPublisher(pusher_handle_);

        if (flag  == DANIULIVE_RETURN_OK)
        {
            Debug.Log("    ..");
        }
        else
        {
            Debug.LogError("    ..");
        }

        is_running = true;
    }
OpenPusher 호출()

    private void OpenPusher()
    {
        if ( java_obj_cur_activity_ == null )
        {
            Debug.LogError("getApplicationContext is null");
            return;
        }

        int audio_opt = 1;
        int video_opt = 1;

        pusher_handle_ = NT_PB_U3D_Open(audio_opt, video_opt, video_width_, video_height_);

        if (pusher_handle_ != 0)
            Debug.Log("NT_PB_U3D_Open success");
        else
            Debug.LogError("NT_PB_U3D_Open fail");
    }
InitAndSetConfig()

    private void InitAndSetConfig()
    {
        if (is_hw_encode_)
        {
            int h264HWKbps = setHardwareEncoderKbps(true, video_width_, video_height_);

            Debug.Log("h264HWKbps: " + h264HWKbps);

            int isSupportH264HWEncoder = NT_PB_U3D_SetVideoHWEncoder(pusher_handle_, h264HWKbps);

            if (isSupportH264HWEncoder == 0)
            {
                Debug.Log("Great, it supports h.264 hardware encoder!");
            }
        }
        else {
            if (is_sw_vbr_mode_) //H.264 software encoder
            {
                int is_enable_vbr = 1;
                int video_quality = CalVideoQuality(video_width_, video_height_, true);
                int vbr_max_bitrate = CalVbrMaxKBitRate(video_width_, video_height_);

                NT_PB_U3D_SetSwVBRMode(pusher_handle_, is_enable_vbr, video_quality, vbr_max_bitrate);
                //NT_PB_U3D_SetSWVideoEncoderSpeed(pusher_handle_, 2);
            }
        }

        NT_PB_U3D_SetAudioCodecType(pusher_handle_, 1);

        NT_PB_U3D_SetFPS(pusher_handle_, 25);

        NT_PB_U3D_SetGopInterval(pusher_handle_, 25*2);

        //NT_PB_U3D_SetSWVideoBitRate(pusher_handle_, 600, 1200);
    }
ClosePusher()

    private void ClosePusher()
    {
        if (texture_ != null)
        {
            UnityEngine.Object.Destroy(texture_);
            texture_ = null;
        }

        int flag = NT_PB_U3D_StopPublisher(pusher_handle_);
        
        if (flag == DANIULIVE_RETURN_OK)
        {
            Debug.Log("    ..");
        }
        else
        {
            Debug.LogError("    ..");
        }

        flag = NT_PB_U3D_Close(pusher_handle_);

        if (flag == DANIULIVE_RETURN_OK)
        {
            Debug.Log("    ..");
        }
        else
        {
            Debug.LogError("    ..");
        }

        pusher_handle_ = 0;

        NT_PB_U3D_UnInit();

        is_running = false;
    }
테스트 에 편리 하도록 Update()는 현재 시간 을 갱신 합 니 다:

    private void Update()
    {
        //      
        hour = DateTime.Now.Hour;
        minute = DateTime.Now.Minute;
        millisecond = DateTime.Now.Millisecond;
        second = DateTime.Now.Second;
        year = DateTime.Now.Year;
        month = DateTime.Now.Month;
        day = DateTime.Now.Day;

        GameObject.Find("Canvas/Panel/LableText").GetComponent<Text>().text = string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D2} " + "{4:D4}/{5:D2}/{6:D2}", hour, minute, second, millisecond, year, month, day);
    }
관련 이벤트 처리

 public void onNTSmartEvent(string param)
    {
        if (!param.Contains(","))
        {
            Debug.Log("[onNTSmartEvent] android      ");
            return;
        }

       string[] strs = param.Split(',');

       string player_handle =strs[0];
       string code = strs[1];
       string param1 = strs[2];
       string param2 = strs[3];
       string param3 = strs[4];
       string param4 = strs[5];
        
       Debug.Log("[onNTSmartEvent] code: 0x" + Convert.ToString(Convert.ToInt32(code), 16));

        String publisher_event = "";

        switch (Convert.ToInt32(code))
        {
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_STARTED:
                publisher_event = "  ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTING:
                publisher_event = "   ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTION_FAILED:
                publisher_event = "    ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTED:
                publisher_event = "    ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_DISCONNECTED:
                publisher_event = "    ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_STOP:
                publisher_event = "  ..";
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_RECORDER_START_NEW_FILE:
                publisher_event = "           : " + param3;
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_ONE_RECORDER_FILE_FINISHED:
                publisher_event = "          : " + param3;
                break;

            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_SEND_DELAY:
                publisher_event = "    : " + param1 + "   :" + param2;
                break;

            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:
                publisher_event = "  : " + param1 + "   :" + param3;

                if (Convert.ToInt32(param1) == 0)
                {
                    publisher_event = publisher_event + "      ..";
                }
                else
                {
                    publisher_event = publisher_event + "      ..";
                }
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUBLISHER_RTSP_URL:
                publisher_event = "RTSP  URL: " + param3;
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_RESPONSE_STATUS_CODE:
                publisher_event = "RTSP status code received, codeID: " + param1 + ", RTSP URL: " + param3;
                break;
            case EVENTID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_NOT_SUPPORT:
                publisher_event = "      RTSP  ,    RTSP URL: " + param3;
                break;
        }

        Debug.Log(publisher_event);

    }
총결산
위 절 차 를 통 해 Unity 환경 에서 화면 이나 카메라 데 이 터 를 구현 하고 밀리초 단위 로 체험 하 는 RTMP 푸 시 와 재생 을 실현 할 수 있 으 며 관심 있 는 개발 자 는 참고 할 수 있 습 니 다.
이상 은 안 드 로 이 드 가 유 니 티 3D 에서 RTMP 푸 시 를 실현 하 는 예제 의 상세 한 내용 입 니 다.안 드 로 이 드 가 유 니 티 3D 에서 RTMP 푸 시 를 실현 하 는 데 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기