Qt 5.8.0 WebEngine 모듈 빌드

보통은 그냥 Qt 홈페이지에서 빌드된것을 받아서 설치해도된다. 단, 5.8.0은 배포중인 VS 2017 타겟 바이너리가 없고, 디버깅 시 상황에 따라서는 약간 더 유리하기때문에 직접 빌드하는걸 선호한다. (그리고 그냥 갠적인 취향 약 80%) 이전에 누수를 찾을 수 없어 직접 빌드하여 QtSql의 ODBC 플러그인 메모리 누수 버그를 찾아내고 코드 리뷰에 올리고 커밋하여 아마도 5.6.0버전부터 적용되어있다는건 안비밀(…)

일단 두서없는 글이였지만 이것을 참조하여 OS의 비 유니코드 환경을 영어(미국)으로 바꾸는것이 이롭다.

이번에도 직접 빌드 삽질. 5.7.0과는 다르게 필요한 것들은 다 있는데 configure 후 nmake(or jom)을 해도 웹 엔진이 빌드되지않았다. 영문 문서…에서는 일단 해석도 잘 못하고 그냥 봤을때는 별다른 언급이 없었다. 정말 아무리 찾아봐도 별다른 내용이 없었다. (덕분에 5~6번은 distclean & build 한거같다.)

문서에 Qt 개별 모듈을 받아서 빌드 언급이 잠깐있어서 혹시나하여 소스코드에서 qtwebengine 폴더로 이동 후 qmake & nmake(or jom)을 실행하니 빌드가되었다. 아마도 이게 워낙 오래걸리고 덩치가 커서 기본적으로 skip 처리되어있는거 아닌가 싶다. 하지만 규모가 큰 C++ 프로젝트는 오류 한두개 생기는 법. 그래서 직접 빌드를 해본 내용을 정리.


환경 1
Visual Studio Community 2015 Update 3 (최소 Update 2가 요구된다.)
Windows SDK 10.0.15063.137

환경 2
Visual Studio Community 2017
Windows SDK 10.0.1563.137 (Visual Studio 2017에서 함께 설치되는 Windows SDK 10은 지우고 ISO 파일을 받아서 다시 깔았다. 필요에 의해서였는데 왜인지 기억이 안난다 -_-)


공통
Perl 최신버전 (Qt 문서에서는 Active Perl로 명시되어있지만 Strawberry Perl로도 가능)
Python 2.7.5 or later (Qt 문서에서는 2.7.5 or later로 명시되어있지만 3버전으로 테스트 안해봤음)
메모리는 8기가 이상.. 왠만하면 16기가 이상을 권장한다. 이것역시 WebEngine에서 사용하는 Chromium의 코그가 워낙 방대해서 메모리에 파일캐쉬를 많이 못하면 디스크 IO가 많이발생하여 빌드 속도에도 영향이있다.


Windows SDK 10을 설치하면 mt.exe 파일을 못찾는 경우가 발생한다. 명령줄에서 mt를 쳐서 명령을 못찾는다면 아래처럼 환경변수에 추가해야한다.
32비트 도구 프롬포트 환경
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x86
64비트 도구 프롬포트 환경
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64


환경 1에서의 WebEngine 에러 수정
코드 리뷰: https://codereview.chromium.org/2317773002/patch/60001/70005

소스코드 폴더 기준으로 “qtwebengine\src\3rdparty\chromium\device\bluetooth” 경로의 bluetooth_task_manager_win.cc 파일을 열고 OnGetGattEventWin 함수가 정의된 157줄을 void 뒤 CALLBACK 추가하여 void CALLBACK OnGetGattEventWin으로 정의를 변경

환경 2에서의 configure 에러 수정
코드 리뷰: https://codereview.qt-project.org/#/c/177743
이건… 수정할게 좀 많다. 그냥 이 페이지를 참고해서 비교하어 수정하는게 나을것같다. qalgorithms.h파일의 경로는 “qtbase\src\corelib\tools”이다.
만약 직접 수정하기가 좀 그렇고 5.8.0버전의 코드를 빌드한다면 이 주소로 파일을 받은다음 압축을 풀고 이름을 원래대로 수정한다음 덮어씌워도 된다.


아래는 내가 사용한 configure 명령 줄
configure -opensource -confirm-license -prefix D:\OpenSource\Qt5.8.0 -opengl dynamic
opengl 옵션을 지정안하면 es2로 설정되고 5.5부터는 dynamic을 기본으로 사용하는 것 같다. (참고)
prefix는 빌드 후 nmake install 하면 바이너리와 헤더가 설치되는 경로.


configure 명령이 완료된 후 nmake(or jom)을하면 문제없이 빌드 될것이며 이후 nmake install(or jom install)을하면 기본 Qt 모듈들이 복사될것이고, WebEngine을 빌드하려면 소스코드 폴더에서 qtwebengine 폴더로 이동한 후 qmake하고 역시나 nmake(or jom)하여 빌드, nmake install(or jom install)하면된다.

단지 주의할것으로는 perl, python명령이 실행되는지, flex, bison, gperf명령이 실행되는지 확인하는것이 좋다. Qt 소스코드 내 gnu 명령어들이 있으니 아래처럼 환경변수를 변경하여 재공되는거로 쓰는게 이로울거같다. (소스가 “D:\OpenSource\qt-everywhere-opensource-src-5.8.0″에 있다는 가정)

set PATH=%PATH%;D:\OpenSource\qt-everywhere-opensource-src-5.8.0\gnuwin32\bin;D:\OpenSource\qt-everywhere-opensource-src-5.8.0\qtbase\bin

환경변수가 잘 설정되었다면 아래와같이 각각의 버전정보를 볼 수 있다.

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>python --version
Python 2.7.13

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>perl --version

This is perl 5, version 24, subversion 1 (v5.24.1) built for MSWin32-x64-multi-thread

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.


D:\OpenSource\qt-everywhere-opensource-src-5.8.0>bison --version
bison (GNU Bison) 3.0
Written by Robert Corbett and Richard Stallman.

Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>flex --version
flex 2.5.37

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>gperf --version
GNU gperf 3.0.1
Copyright (C) 1989-1998, 2000-2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Douglas C. Schmidt and Bruno Haible.

뭐… 갠적으로는 webengine을 사용할 일이 없지만 왠지 5.7 빌드할때와 달라서 불필요한 삽질을 한거같다(…)

Objective-C와 Swift에서 NSData(Data) 데이터 단순 탐색

Objective-C 코드 (bytes는 NSData 클래스 객체에서 bytes를 호출하여 얻은 데이터 포인터)

for(uint32_t i = 0; i < dataSize - 4; i++)
{
    uint32_t startCode = *(uint32_t *)(bytes + i);

    if(startCode == 0x01000000)
    {
        [points addObject:[NSValue valueWithPointer:bytes + i]];
        [nalSizes addObject:[NSNumber numberWithInt:4]];
        
        i += 3;
    }
    
    if((startCode & 0x00FFFFFF) == 0x00010000)
    {
        [points addObject:[NSValue valueWithPointer:bytes + i]];
        [nalSizes addObject:[NSNumber numberWithInt:3]];
        
        i += 2;
    }
}

 

Swift 코드 (3.0으로 빌드, streamData는 Data 클래스의 객체)

streamData.withUnsafeBytes { (p8: UnsafePointer) in
    while i < count
    {
        if p8.advanced(by: i + 0).pointee == 0 && p8.advanced(by: i + 1).pointee == 0
        {
            if p8.advanced(by: i + 2).pointee == 0 && p8.advanced(by: i + 3).pointee == 1
            {
                offsets.append(i)
                nalSizes.append(4)
                
                i += 4
                
                continue
            }
            if p8.advanced(by: i + 2).pointee == 1
            {
                offsets.append(i)
                nalSizes.append(3)
                
                i += 3
                
                continue
            }
        }
        i += 1
    }
}

 

H264에서 NAL 헤더를 찾는 코드이다. 어쩌다보니 기존에 Objective-C로 코드를 만들어놓은걸 Swift로 옮기다보니... 생각보다 삽질을 많이하게되었다. 프레임워크는 동일하지만 Swift는 기본적으로 포인터 연산을 지원하지않기때문에 C에서의 구조체, 바이너리 데이터를 int형식으로 형변환하여 비교하는 등의 연산에서 자유롭지않아보인다. 동일한 LLVM에서 컴파일되고 1:1 호환 가능하다고는하지만 위와같은 사항 외에도 언어의 특성이있어서 목적은 동일하지만 결국은 코드의 구조는 달라졌다.

딱봐도 Swift의 코드가 비효율적으로 보이지만 초당 1메가정도의 데이터에서 CPU점유율을 보면 1~2%정도만 더 Swift에서 많이 사용한다. 아직 릴리즈 빌드는 찾아본적없어서 export하게되면 또 차이날지는 모르겠지만... 현재로서는 약 2~3시간 삽질을 한 결과 위 코드가 Objective-C의 코드와 가장 근접한 CPU 사용률을 보이는 코드이다.

아래는 순서대로 Objective-C, Swift 코드에서의 CPU 사용률

VideoToolbox 디코더에서 픽셀 포맷을 BGRA와 420YpCbCr를 사용할때의 CPU 점유율 차이

일단 각각의 차이

kCVPixelFormatType_32BGRA 값을 사용할 때

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 값을 사용할 때

하드웨어 스펙

420YpCbCr 색상으로 출력할 때 평균적으로 3~4%정도 점유율이 더 적다. Metal 텍스쳐 두개를 생성하고 GPU에서 색상변환하기위해 소비되는 연산보다 VideoToolbox에서 BGRA로 변환하여 CVImageBufferRef 객체를 생성하는 부하가 더 큰것으로 보인다.

맥에서 어느정도 끝나면 iOS앱에도 Metal을 사용해서 얼마나 차이나는지 비교해봐야겠다.

NAS의 DLNA(미디어 서버)를 사용해본 결과

  1. NAS의 미디어 서버를 통하여 영상에서 자막을 사용하려면 MP4나 MKV 컨테이터에 자막을 내장시켜야한다.
  2. 플레이 스테이션 4의 미디어 플레이어는 MP4에 자막을 넣으면 자막인식을 못하는것으로 보임.
  3. 주변의 소문으로는 webOS 3.0을 쓴 LG 스마트 TV가 MKV 컨테이너를 인식하지 못한다고 함.
  4. 플스의 미디어플레이어는 자막에 테두리가 들어가지않음. 즉 흰색 글자로만 표현되고 하얀색의 장면이 표시되고있으면 자막이 안보인다. ‘콘텐츠에서 지정한 대로 클로즈드 캡션 표시하기’ 옵션을 끄고 직접 스타일을 지정하면 된다. 단, 한글폰트의 윤곽선 품질은 형편없다. 하는 수 없이 배경색을 25%주어서 흰색 화면에서 글자가 좀 더 잘보이게 하여 어느정도 해결. (그마저도 배경색이 폰트의 위/아래 여분의 영역없이 들어가버려서 불만족) 기분탓인지 모르겠지만 오늘(2017-03-28) 업데이트 된 3.00버전에서는 한글자막의 배경색도 나름 만족스러울정도로 적용된다.
  5. 시놀로지 나스에서 호환성 옵션으로 재공되는 영상의 트랜스코딩이란것을 활성화하여 재생하면 자막이 빠져버린다.

 

이정도가 약 일주일동안 이리저리 사용해본 결론. 플스의 미디어 플레이어가 자막에 테두리효과가 없이 흰색 글자로만 표현된다는건 큰 실망이였다.

메뉴얼에는 단순히 H.264 High Profile, Level 4.2까지 지원하고 지원하는 영상의 색상정보는 표기되어있지않은데 재생해본결과 YUV 444 형식이면 재생이안되고 YUV 420이라도 10bit 컬러깊이를 사용하는 영상은 재생이되지만 감상할 수 없을정도로 영상이 끊긴다.

분명 하드웨어 성능으로는 전혀 무리없이 디코딩 가능할것으로 보이는데 포터블 기기도아니고 멀티미디어를 재생하는 미디어 플레이어가 이러한 제한이있다는것이 의외였다. (소프트웨어 디코더의 라이센스 문제일가능성이 크지만.)

PC를 쓰지않고 TV나 모니터로 자막을 지원하는 플레이어로 영상을 보려면 IPTV의 셋톱박스에서 지원하는 USB 미디어의 플레이어를 쓰는것이 훨신 유용할것이라고본다.

DS Cloud의 모바일버전은 쓸만하지않다

결론을 말하자면 그냥 구글드라이브 쓰자. 기본재공 드라이브의 용량이 부족하다면 그냥 과금하여 사용하자. 기능확인을 위해 구글 드라이브로 사진 동기화 방법을 알아봤지만 iCloud에 동기화하여 사용중이기때문에 이 글을 쓰고나서는 구글 드라이브로의 동기화는 해제할것이다. (아이폰은 그냥 iCloud가 좋다. 그래도 종종 날려먹는 파일이 생긴다는 소문이있으니 iCloud와 Google Drive 둘 다 동기화하는것도 나쁘지않다.)

이전에 아이폰 베타버전 펌웨어 잠깐 올려보다가 꼬여버려서 다른건 다 iCloud 동기화 시켜놓았지만 용량이안되어 사진만 iCloud에 동기화하지 않도록 했다가 전부 날린적이있었다. 그나마 OneDrive에 용량이차서 당시 기준 일년치 사진을 동기화하지 못하고 그 이전 사진과 동영상이 남아있었는데 그것마저아니였다면 수년동안 찍었던 사진들을 전부 날릴뻔한적이있었다. 지금도 그 일년동안의 사진이 아깝다. 외냐면 이전보다 조금은 더 활동적이고싶어 밖에 돌아다니면서 돌아다녔던 곳들을 찍었고 출장이였지만 외국에서도 찍은사진들이 유난히 많았던 일년이였으니까.

그 후로는 그냥 저장용량을 추가구입하여 iCloud에 동기화한다. 아마 ‘난 그런거 당하지않아’라던지 ‘그정도로 중요하지않아’와 같은 마음가짐으로 한달 천얼마 아깝다고 안하는 사람 주변에 보이는데… 겪어보면 정말 그럴까? 난 게임을하면서 찍은 스크린샷이나 고등학교때, 대학교때 찍었던 사진 전부(일부는 날렸을테지만) 가지고있는 성격인데 베타버전 펌웨어를 사진 백업없이 했다가 몇시간만에 일년치의 사진을 날려먹어보니 일년에 1~2만원 사용하는거 아깝지않았다.

아래는 아이폰 기준으로 구글드라이브로 사진을 동기화하는 방법이다. Continue reading DS Cloud의 모바일버전은 쓸만하지않다