發表文章

目前顯示的是 1月, 2020的文章

轉換/反轉換BASE64資料及HEX字串

Convert hex string to binary file printf 1716d547cd7c0398bd244ac06c8a2ec8 | xxd -r -p > x.bin # show original bytes xxd x.bin # 00000000: 1716 d547 cd7c 0398 bd24 4ac0 6c8a 2ec8  ...G.|...$J.l... Convert binary file to base64 file base64 x.bin > x.base64      # default line wrapping=76 base64 -w 0 x.bin > x.base64 # w/o line wrapping # show base64 cat x.base64 # FxbVR818A5i9JErAbIouyA== Revert base64 file to binary base64 -d x.base64 > r_x.bin # show reverted bytes xxd r_x.bin ---- Convert hex string to base64 string printf 1716d547cd7c0398bd244ac06c8a2ec8 | xxd -r -p | base64 # FxbVR818A5i9JErAbIouyA== Revert base64 string to binary file echo -n "FxbVR818A5i9JErAbIouyA==" | base64 -d - > x.bin # show bytes xxd x.bin # 00000000: 1716 d547 cd7c 0398 bd24 4ac0 6c8a 2ec8  ...G.|...$J.l... ---- Convert plain text to base64 string echo -n "{your-plain-text}" | base64 # e3lvdXItcGxhaW4tdGV4dH0= Revert base64 string to p

使用bento4同時產生DASH和HLS

承上一篇: 使用bento4產生DASH或CENC/CBCS加密的DASH 同時產生 無加密 DASH和HLS mp4dash -f -o bento4_clear --mpd-name=clear.mpd \   --hls \   --hls-master-playlist-name=clear.m3u8 \   --hls-media-playlist-name=track.m3u8 \   fragmented.mp4 --hls-master-playlist-name指定的是HLS的主播放清單(影片+聲音) --hls-media-playlist-name指定的是HLS的媒體播放清單(單純影片或是聲音) 同時產生 加密 DASH和HLS 這裡用下面的key和iv值做範例 VID_KID=6c145258e3df0584cd61f57e0ed5cba1 VID_KEY=5a867de28e7a029c2e995687b8992693 AUD_KID=1716d547cd7c0398bd244ac06c8a2ec8 AUD_KEY=0c63c5c13d0d25d697f5a38bb1ce7190 COMM_IV=c35263c8381d0b6b80f93360a5ca2ee6 mp4dash -f \   --encryption-key=video:${VID_KID}:${VID_KEY}:${COMM_IV},audio:${AUD_KID}:${AUD_KEY}:${COMM_IV} \   --encryption-cenc-scheme=cbcs \   -o bento4_cbcs \   --mpd-name=encrypted.mpd \   --hls \   --hls-master-playlist-name=encrypted.m3u8 \   --hls-media-playlist-name=enc_track.m3u8 \   fragmented.mp4 上面輸出的HLS是用SAMPLE-AES, 同Apple提供的加密方法 #EXT-X-KEY:METHOD=SAMPLE-AES bento4不支援其他的加密方法(cenc,cens,cbc1)同時輸出

使用bento4產生加密的DASH

參考: https://www.bento4.com/developers/dash/encryption-and-drm/ https://github.com/Dash-Industry-Forum/dash.js/wiki/ Step 1. 下載Bento4工具 從bento4官網上下載已編譯好的二進位檔 https://www.bento4.com/downloads/ Step 2. 產生fMP4影片檔 建議使用mp4影片,使用bento4的mp4fragment將mp4正規化成fMP4檔案 mp4fragment original.mp4 fragmented.mp4 Step 3. 決定加密的KEY和IV值 可參考openssl rand -hex 16產生key和iv值 Step 4. 將fMP4加密並輸出成DASH 以下範例使用的加密key和iv VID_KID=6c145258e3df0584cd61f57e0ed5cba1 VID_KEY=5a867de28e7a029c2e995687b8992693 AUD_KID=1716d547cd7c0398bd244ac06c8a2ec8 AUD_KEY=0c63c5c13d0d25d697f5a38bb1ce7190 COMM_IV=c35263c8381d0b6b80f93360a5ca2ee6 用CENC加密的DASH串流 cenc使用aes-128-ctr應不需要iv值, 這裡只是方便打指令都寫上 mp4dash -f \   --encryption-key=video:${VID_KID}:${VID_KEY}:${COMM_IV},audio:${AUD_KID}:${AUD_KEY}:${COMM_IV} \   --encryption-cenc-scheme=cenc \   -o bento4_cenc \   --mpd-name=encrypted.mpd \   fragmented.mp4 用 CBCS 加密的DASH串流 mp4dash -f \   --encryption-key=video:${VID_KID}:${VID_KEY}:${COMM_IV},audio:${AUD_KI

用ffmpeg解交錯deinterlace將1080i影片轉成1080p影片

From: https://video.stackexchange.com/questions/17396/how-to-deinterlacing-with-ffmpeg 查看有哪些deinterlace可用 ffmpeg -filters | grep -i deinterlace  TS. bwdif             V->V       Deinterlace the input image.  T.. nnedi             V->V       Apply neural network edge directed interpolation intra-only deinterlacer.  TS. w3fdif            V->V       Apply Martin Weston three field deinterlace.  TS. yadif             V->V       Deinterlace the input image. bwdif, w3fdif, yadif和可直接使用,nnedi算法還需要給予參數權重 https://ffmpeg.org/ffmpeg-all.html#nnedi 這裡使用比較快速的yadif算法進行解交錯deinterlace ffmpeg -i interlace.ts -vf yadif -c:v libx264 -preset slow -crf 19 -c:a copy deinterlaced.ts -crf就類似量化參數QP, 數值愈低畫面品質愈高, 數值愈高畫面品質愈低 如果要順便改畫面幀率frame rate(fps)可加上-r https://ffmpeg.org/ffmpeg-utils.html#Video-rate -r格式是frame_rate_num/frame_rate_den 一些常用的-r參數: 50/1 pal=25/1 film=24/1 60000/1001=59.94 ntsc=30000/1001=29.97 24000/1001=23.97 其他關於h264編碼器的參數說明請見官方文件 https://trac.ffmpeg.org

用ffmpeg產生dash串流並播放

這裡簡化這篇的指令 https://stackoverflow.com/questions/48256686/how-to-create-multi-bit-rate-dash-content-using-ffmpeg-dash-muxer 產生多個bitrate及解析度的串流 ./ffmpeg -y -i /content/FHD.ts \   -c:v libx264 \   -c:a copy \   -map 0:v:0 -b:v:0 250k -filter:v:0 "scale=-2:240" -profile:v:0 baseline \   -map 0:v:0 -b:v:1 750k -filter:v:1 "scale=-2:480" -profile:v:1 main \   -map 0:v:0 -b:v:2 1.5M -filter:v:2 "scale=-2:720" -profile:v:2 high \   -map 0:v:0 -b:v:3 8M   -profile:v:3 high \   -map 0:a:0 \   multiple_bitrate.mp4 這裡設定的影片bitrate和解析度分別為 250k, 240p(426x240) 750k, 480p(854x480) 1.5M, 720p(1280x720) 8M, 原始大小(1920x1080) audio不改變bitrate 用多birate及解析度的串流產生dash ./ffmpeg -y -re -i multiple_bitrate.mp4 \   -map 0 \   -f dash sample_dash.mpd 產生出dash串流檔案,包括一個mpd(xml格式), 還有一大堆類似HLS的影音segment init-stream0.m4s init-stream1.m4s init-stream2.m4s ... chunk-stream0-00001.m4s chunk-stream0-00002.m4s chunk-stream0-00003.m4s .... 如果要作其他調整請參考ffmpeg官方文件 ht

啟用ffmpeg播放dash串流能力

先確認是否已有dash播放能力, 如果和下面相同有D應該就不需要重編譯 $ ./ffmpeg -formats | grep dash  DE dash            DASH Muxer  DE webm_dash_manifest WebM DASH Manifest https://stackoverflow.com/questions/28848917/playing-mpeg-dash-streaming-with-ffmpeg 安裝播放DASH需要的xml parser開發包 sudo apt-get install libxml2-dev 清除之前建置跟config make distclean 重新config ./configure \   --enable-demuxer=dash --enable-libxml2 \   --enable-ffplay 建置ffmpeg make -j8 播放DASH ./ffplay  sample.mpd

把ffmpeg加入AV1編解碼器

感謝大神彙整各項編解碼器加入方法, 請參考 https://gist.github.com/sparrc/026ed9958502072dda749ba4e5879ee3 安裝並編譯AV1編解碼器 # Install libaom from source. sudo apt-get install -y cmake mkdir -p ~/ffmpeg_sources/libaom && \   cd ~/ffmpeg_sources/libaom && \   git clone https://aomedia.googlesource.com/aom && \   cmake ./aom && \   make -j 16 && \   sudo make install 下載或升級ffmepg程式碼庫 git clone https://git.ffmpeg.org/ffmpeg.git 已確定下面這個版本,已可以編譯av1包 commit 81172b5e3ac0d3130ff7b639ed7efed5baa1195c (origin/master, origin/HEAD) Author: Paul B Mahol Date:   Thu Jan 2 17:24:01 2020 +0100     avfilter/af_dynaudnorm: fix previous commit         We still need to analyze frame for amplification at EOF. 重新編譯ffmepg 如果曾經編譯過ffmpeg,建議先清除暫存,我有遭遇過沒清除一直都編譯不進去的狀況 make distclean ./configure \   --enable-libaom \   --enable-ffplay make -j 16 https://trac.ffmpeg.org/wiki/Encode/AV1

Ubuntu 16.04安裝新版pip和pip3後無法執行(No such file or directory)

在進行pip install時python會建議安裝新版本pip,雖然可以透過pip install pip進行升級就好,但是如果用sudo升級pip會發生pip指令無法使用的狀況。(指令如下) sudo pip install --upgrade pip sudo pip3 install --upgrade pip 這是因為原本Ubuntu的pip指令是透過用apt-get安裝,pip在10.0.0版本有做一些改變,所以指令有改動,導致pip自我安裝新版後無法使用pip指令 預設Ubuntu 16.04安裝的pip應該是8.1.1版,用pip -V可顯示版本 pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7) (2020-03-02 pip,pip3更新到20.0.2) $ pip3 -V pip 20.0.2 from /usr/local/lib/python3.5/dist-packages/pip (python 3.5) $ pip -V pip 20.0.2 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7) 解法1. 修改Ubuntu內pip或pip3指令 sudo vim /usr/bin/pip 改寫成 #!/usr/bin/python # for pip > 10.0.0 import sys from pip import __main__ if __name__ == '__main__':     sys.exit(__main__._main()) 原本Ubuntu原本出問題的pip內容是 #!/usr/bin/python # -*- coding: utf-8 -*- import re import sys from pip._internal.cli.main import main if __name__ == '__main__':     sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '',

用ffmpeg加密/解密播放CENC的mp4

MPEG Common Encryption (CENC) 說明請參考wiki https://en.wikipedia.org/wiki/MPEG_Common_Encryption for ISOBMFF, Common encryption in ISO base media file format files (ISO/IEC 23001-7:2016) for MPEG-TS, Common encryption of MPEG-2 transport streams (ISO/IEC 23001-9:2016) 確認ffmpeg是否有CENC功能 $ ./ffmpeg -h muxer=mp4 | grep enc ...   -encryption_scheme      E......... Configures the encryption scheme, allowed values are none, cenc-aes-ctr   -encryption_key         E......... The media encryption key (hex)   -encryption_kid         E......... The media encryption key identifier (hex) 用CENC加密mp4 ./ffmpeg -i /content/sample.ts \ -c copy \ -encryption_scheme cenc-aes-ctr \ -encryption_key 76a6c65c5ea762046bd749a2e632ccbb \ -encryption_kid a7e61c373e219033c21091fa607bf3b8 \ cenc.mp4 預設只支援AES CTR模式, 可參考wiki解說 https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR) 就是把counter編號(編號起始值可以自訂,就類似IV)拿去加密後再跟明文xor產生密文, 這個方法的好處就是可以把counter的加密結果做成表,加速加密運算的進行。然後解密的時候也支

用VLC打廣播封包

cvlc h264_test.mpg :file-caching=300 --loop --sout udp:224.1.2.4:1234

[APP]從JNI傳送字串資料送到Java層遭遇\0問題

一般會認為,直接將字串資料直接呼叫到JNI的NewStringUTF, jstring的array中即可, 就像是下面這樣 char* p_str = ""; //你的字串資料 int len = ; //你的字串資料長度 jstring jstr = m_jenv->NewStringUTF(p_str); return jstr; 但是如果你的字串是中有包含'\0'字元時,就無法這麼做,例如:"abc\0cde\0",因為NewStringUTF是以\0作為結束符號,你得字串長度就會不正確。 所以要傳上述字串回到java層,就需要一套轉換方法,比較簡單的方式是使用jbyte陣列來傳遞,像是下面這樣。 jbyteArray jbarray = m_jenv->NewByteArray(len); m_jenv->SetByteArrayRegion(jbarray, 0, len, (const jbyte*)p_str); return jbarray; JNI回呼的Java方法大概會長這樣     public void OnCallbackTwoString (byte[] b) {         String s;         try {             s = new String(b, "UTF-8"); // or Charset.defaultCharset()             ....         } catch (UnsupportedEncodingException e) {             Log.e(TAG, "OnCallbackTwoString:", e);         }     } 在JNI回呼OnCallbackTwoString時使用"([B)Z" 實際上遭遇\0的字元的狀況很多,尤其你的資料是透過native來的從其他sever來的多國語語言文字,都會遭遇這個問題。 另外,如果你是從Java送到JNI層, 建議是用GetStringUTFChars將java的unicode轉換成utf-8,

用ffmpeg加密並產生HLS串流

AES-128 CBC 加密的HLS串流 1. 產生keyinfo檔案 openssl rand -hex 16 > crypto.key cat crypto.key | xxd -r -p > crypto.bin echo "crypto.bin" > mine_key.keyinfo echo "crypto.bin" >> mine_key.keyinfo openssl rand -hex 16 >> mine_key.keyinfo keyinfo檔案內的第1行是解密key檔案位置,第2行是加密key檔案位置,iv值(不是檔案) $ cat mine_key.keyinfo crypto.bin crypto.bin 1e6ae3ae8b573d371bc19525afed405f 2. 產生HLS串流 因為我的ffmpeg是自己編譯的版本,所以呼叫路徑是這樣 /home/mirochiu/test/ffmpeg/ffmpeg -y -i source.ts \   -c copy -map 0 \   -f hls -hls_time 10 -hls_list_size 0 -start_number 1 \   -hls_key_info_file mine_key.keyinfo \   -hls_playlist_type vod \   -hls_segment_filename 'test-%03d.ts' test.m3u8 m3u8內容類似下面這樣 # EXTM3U # EXT - X - VERSION : 3 # EXT - X - TARGETDURATION : 10 # EXT - X - MEDIA - SEQUENCE : 1 # EXT - X - KEY : METHOD = AES - 128 , URI = "crypto.bin" , IV = 0x1e6ae3ae8b573d371bc19525afed405f # EXTINF : 9.072711 , test -0 01 . ts # EXTINF : 10.140089 , test -0

Android shell下的pm指令

印出已安裝的package pm list packages 在Android 7之後推出使用者機制之後,用這個指令能得到的套件不再是所有套件 印出安裝套件的位置 pm path {package name} package:/data/app/{xxxx}/base.apk 可用來判斷是外裝的版本還是內建在系統的版本 /data/底下是外裝的版本, /system/底下是內建的 印出package版本,intent filter,權限,最佳化 dumpsys package {package name} 我自己很偷懶是會接搜尋DEFAULT印出啟動的activity dumpsys package {package name} | grep -C 5 DEFAULT 常搭配grep印出版本資訊 dumpsys package{package name} | grep version 印出package所有資訊(含使用統計) pm dump {package name} 不知道要查套件的哪個資訊,用這個指令印出來再查 啟用/關閉package pm enable {package name} pm disable {package name} 賦予package特定的runtime permission pm grant {package name} {permission name} 只有targeSDKVersion指定在Android 6.0以上版本的package才能用這個方式賦予權限,不然這指令會寫legacy app not support runtime permission。在Android 6.0以下解決方式,就是重裝該package 有些permission是特殊的,需要開系統設定頁面才能賦予, 例如最上層繪製內容的android.permission.SYSTEM_ALERT_WINDOW, 得用下面這個方式開啟設定頁, am start -a "android.settings.action.MANAGE_OVERLAY_PERMISSION" \   -d "package:{package name}" \   "c

取得apk的套件名稱,權限,AndroidManifest.xml

參考https://elinux.org/Android_aapt 先安裝AAPT(Android Asset Packaging Tool) Android SDK裏面有或者是安裝Ubuntu的套件 sudo apt-get install google-android-build-tools-installer 取得APK所需權限 aapt dump permissions {apk名稱} package: apk的套件名稱 uses-permission: name='android.permission.INTERNET' uses-permission: name='android.permission.BLUETOOTH' uses-permission: name='android.permission.BLUETOOTH_ADMIN' uses-permission: name='android.permission.ACCESS_COARSE_LOCATION' uses-permission: name='android.permission.ACCESS_FINE_LOCATION' 取得APK的AndroidManifest.xml aapt dump xmltree {apk名稱} AndroidManifest.xml 這指令會印出AndroidManifest.xml的內容,但是不是可以直接在Android stuido中可使用的xml檔案 取得APK的套件名稱,vesionCode,sdk,targetSdkVersion,uses-permission,uses-feature,locales,density等資訊 aapt dump badging {apk名稱} showPermission(){     aapt dump permissions $1 } showManifest(){     aapt dump xmltree $1 AndroidManifest.xml } showAppVersion(){     aapt dump badging $1 | grep &quo

手動移除android app

adb shell底下 列出已安裝的所有app pm list package 一般會加上grep去過濾名稱 pm list package | grep -i {xxx} -i是忽略大小寫 手動移除 pm uninstall {package name} 只針對某一個使用者移除app (在設定頁中會看到,目前使用者無安裝此app) pm uninstall --user 0 {package name}

取得/設定Android裝置的解析度,DPI(Density)

在adb shell下使用window manage的指令可以取得解析度,DPI(Density)等資訊 取得螢幕解析度 wm size 設定螢幕解析度 wm size 寬x高 重置螢幕解析度 wm size reset 設定DPI(Density) wm density 160 當螢幕解析度固定時,density愈大,UI介面看起來也會變大 例如1280x720解析度下,density設240, 顯示的UI介面會變大 重置DPI(Density)的修改 wm density reset

使用HTTP POST時Django總是回覆403

使用HTTP POST時Django總是使用回覆403, 但是直接用get就可以正常看到寫好的頁面 用curl測試 curl -H "Content-Type:application/json" \ -X POST \ -d '{"from":"10.0.0.4","prod":"MY_NEW_PROD","result":"Success","action_time":"2020-01-14 09:29:41.112"}' \ http://10.0.0.3:8080/api/sendMsg 取得的頁面寫道   Forbidden (403)   CSRF verification failed. Request aborted.   You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties. 查了一下是因為Django預設機制會檢測不合法行為, 認為一個正規的POST應該要帶有一些必要資訊避免被跨站攻擊。 但是我只是要模擬Server接收POST資訊沒有真的要拿來架站, 所以套用解法: https://blog.csdn.net/u010358168/article/details/77511445 註解掉settings.py的django.middleware.csrf.CsrfViewMiddleware,就可以正常接收POST

啟動Android service並帶入參數

1. 加入service 事前init.rc加入service service service_xx  /system/bin/xx ....   disabled   oneshot 2. 改使用權限 非system/root啟動service,需修改權限 要改system/core/init/property_service.c請參考下面這篇 設定ctl.start 屬性啟動init.rc 中service以及許可權問題 3. 啟動service * 在shell使用   setprop ctl.start "service_name:arg1 arg2 arg3..." 可參考 Android Service with dynamic arguments * 在App中使用   SystemProperties.set("ctl.start", "service_name:arg1 arg2 arg3..."); 備註:參數功能在我手邊的裝置上(Android 7.0(含)以下版本)測試失敗

Ubuntu16.04之後的網路裝置資訊

顯示IPv4/IPv6 IP,DNS,Gateway等全部資訊 $ nmcli device show GENERAL.DEVICE:                         enp0s31f6 GENERAL.TYPE:                           ethernet GENERAL.HWADDR:                         34:97:F6:83:84:EC GENERAL.MTU:                            1500 GENERAL.STATE:                          100 (connected) GENERAL.CONNECTION:                    intra-yhchiu(Wired-enp0s31f6) GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/3 WIRED-PROPERTIES.CARRIER:               on IP4.ADDRESS[1]:                         10.131.2.183/20 IP4.GATEWAY:                            IP4.ROUTE[1]:                           dst = 224.0.0.0/4, nh = 0.0.0.0, mt = 100 IP4.ROUTE[2]:                           dst = 172.16.0.0/12, nh = 10.131.3.254, mt = 100 IP6.ADDRESS[1]:                         fe80::3697:f6ff:fe83:84ec/64 IP6.GATEWAY:                            GENERAL.DEVICE:                         enp4s0 GENERAL.TYPE:                           eth