http://my.eoe.cn/682121/archive/1839.html
作者:changkai245發佈於 03月21日訪問(533)評論(0)
1 寫入程式碼 & 軟編碼
寫入程式碼:通過調用Android系統內建的Camera錄製視頻,實際上是調用了底層的高清編碼硬體模組,也即顯卡,不使用CPU,速度快
軟編碼:使用CPU進行編碼,如常見C/C++代碼,一般編譯產生的二進位都是的,速度相對較慢。例如使用Android NDK編譯H264產生so庫,編寫jni介面,再使用java調用so庫。
2 原理
① 過程:通過MediaRecoder採集視頻,再將視頻流映射到LocalSocket實現收發
② 原理:詳見【流媒體】H264—MP4格式及在MP4檔案中提取H264的SPS、PPS及碼流 和 “【流媒體】Android 即時視頻採集—MediaRecoder錄製 ”
3 核心代碼
① MediaRecoder視頻採集
視頻採集採用了MediaRecorde錄製方式,詳見 “【流媒體】Android 即時視頻採集—MediaRecoder錄製 ”
② 在initiativeVideo中setOutputFile設定以流方式輸出
1 2 3 4 5 6 7 8 9101112131415 |
// 設定輸出檔案方式: 直接本機存放區 or LocalSocket遠程輸出 if (bIfNativeORRemote == true) // Native { lVideoFileFullPath = strRecVideoFilePath + String.valueOf(System.currentTimeMillis()) + lVideoFileFullPath; mRecVideoFile = new File(lVideoFileFullPath); // mMediaRecorder.setOutputFile(mRecVideoFile.getAbsolutePath()); mMediaRecorder.setOutputFile(mRecVideoFile.getPath()); // called after set**Source before prepare Log.i(TAG, "start write into file~"); } else // Remote { mMediaRecorder.setOutputFile(sender.getFileDescriptor()); // 設定以流方式輸出 Log.i(TAG, "start send into sender~"); } |
③ startRecording
功能:通過這個函數啟動線程實現視頻流映射到LocalSocket,同時實現編碼
12345 |
private void startRecording(){ Log.i(TAG, "##startRecording...."); new Thread(this).start(); } |
run:
@Override
public void run()
{
Log.i(TAG, "##run....");
1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
// defines DataInputStream dataInputStream = null; int offSet=0,tmp=0,beLeft=0; try { dataInputStream = new DataInputStream(receiver.getInputStream()); } catch (IOException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } try { Thread.currentThread().sleep(500); } catch (InterruptedException e1) { e1.printStackTrace(); } // ①方式一:通過查看預先錄製的視頻,需要跳過mdat前面32個位元組(不同硬體平台不同!) try { dataInputStream.read(h264frame, 0, 32); Log.i(TAG, "read mdat from"); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // ②方式二:自動化尋找(待補充) try { h264FileOutputStream = new FileOutputStream("/sdcard/avss/h264.264");//264碼流 Log.i(TAG, "h264FileOutputStream"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { h264FileOutputStream.write(h264head); h264FileOutputStream.write(h264sps); h264FileOutputStream.write(h264head); h264FileOutputStream.write(h264pps); Log.i(TAG, "run-write SPS/PPS to file"); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } while (bIfRecInProcess && (!bIfNativeORRemote)) { try { Log.i(TAG, "**while..."); int h264length = dataInputStream.readInt(); Log.i(TAG, "h264length:"+h264length); tmp=0; offSet = 0; beLeft = 0; h264FileOutputStream.write(h264head); while (offSet < h264length) { beLeft = h264length - offSet; tmp = dataInputStream.read(h264frame, 0, READ_SIZE < beLeft ? READ_SIZE : beLeft); Log.i(TAG, String.format("H264 %d,%d,%d", h264length, offSet, tmp)); offSet += tmp; h264FileOutputStream.write(h264frame, 0, tmp); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } //} |
4 Ref/Related
1
http://blog.csdn.net/zblue78/article/details/6078040
2
http://blog.csdn.net/zblue78/article/details/6083374
3
http://www.docin.com/p-282454756.html
4
http://blog.csdn.net/qwertyuj/article/details/7029836
5
http://www.cnblogs.com/skyseraph/archive/2012/03/31/2427593.html
6
http://www.cnblogs.com/skyseraph/archive/2012/03/23/2415018.html
7
http://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.html
作者:skyseraph
出處:http://www.cnblogs.com/skyseraph/
Email/GTalk: zgzhaobo@gmail.com
聲明:eoe文章著作權屬於作者,受法律保護,轉載時請務必以超連結形式附帶如下資訊
原文作者:
changkai245
原文地址:
http://my.eoe.cn/682121/archive/1839.html