2012-05-23 161 views
6

我試圖通過本地Socket從Android的MediaRecorder發送h264/AAC視頻。目標是通過RTMP或RTSP將視頻發送到WOWZA服務器,但它給我帶來了很多麻煩,現在我只是試圖從LocalServerSocket將數據寫入文件。從MediaRecorder通過LocalSocket流式傳輸視頻

這是一些代碼。對不起,它不是很乾淨,但我花了幾個小時來測試很多事情,現在我的項目很混亂。

在攝像頭活動,將輸出文件設置:

LocalSocket outSocket = new LocalSocket(); 

try { 
    outSocket.connect(new LocalSocketAddress(LOCAL_SOCKET)); 
} catch (Exception e) { 
    Log.i(LOG_TAG, "Error connecting socket: "+e); 
} 
mMediaRecorder.setOutputFile(outSocket.getFileDescriptor()); 

的LocalServerSocket實現:

try { 
    mLocalServerSocket = new LocalServerSocket(mName); 
} catch (Exception e) { 
    Log.e(LOG_TAG, "Error creating server socket: "+e); 
    return; 
} 

while (true) { 

    File out = null; 
    FileOutputStream fop = null; 
    try { 
     mLocalClientSocket = mLocalServerSocket.accept(); 

     InputStream in = mLocalClientSocket.getInputStream(); 

     out = new File(mContext.getExternalFilesDir(null), "testfile.mp4"); 
     fop = new FileOutputStream(out); 

     int len = 0; 
     byte[] buffer = new byte[1024]; 
     while ((len = in.read(buffer)) >= 0) { 

      Log.i(LOG_TAG, "Writing "+len+" bytes"); 
      fop.write(buffer, 0, len); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    finally{ 
     try { 
      fop.close(); 
      mLocalClientSocket.close(); 
     } catch (Exception e2) {} 
    } 
} 

的問題是,由此產生的文件是不會被任何媒體播放器可讀。你認爲這是由於編碼問題?如果我理解得很好,這段代碼應該生成一個二進制文件?!

在此先感謝,歡呼聲。

+0

如果您沒有得到錯誤,它可能是由編碼/文件名問題引起的。你設置了什麼[OutputFormat](http://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html)?也許將其重命名爲'.3gp'或者幫助 - 請參閱[這裏](http://stackoverflow.com/questions/9110711/android-mediarecorder-getting-3gp-instead-of-mpeg4) – zapl

+0

輸出格式是MPEG_4,所以我想應該用.mp4擴展名來確定。此外,如果我直接寫入mMediaRecorder.setOutputFile()中的.mp4文件,它可以很好地工作。 – Simon

+0

是否檢查過像[mediainfo](http://mediainfo.sourceforge.net/en)這樣的內容是否可以讀取已創建視頻的屬性?你也可以嘗試直接生成的文件的二進制比較(至少是頭文件),並通過本地套接字發送文件以檢查生成的文件是否正確。 – zapl

回答

2

好的,我找到了文件無法播放的原因。在MP4和3GPP文件,存在含有該字節的頭部:

ftyp3gp4 3gp43gp6寬的mdat之前

在HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

的4個字節'mdat'標籤代表位於其他'moov'標籤的位置文件結尾。位置通常是在錄製結束時設置的,但由於MediaRecorder無法查找套接字,因此無法將這些字節設置爲正確的值。

我現在的問題是要找到一種方法來製作這樣的文件流式傳輸,因爲它涉及它在錄製結束之前播放。

+3

你有沒有找到一個解決方案,使其流傳? – Houf

+0

嗨西蒙,你有沒有找到一些解決方法..請分享它,我在同一問題stucking –

+0

嗨Ankita。對不起,我們現在放棄了這個項目,所以我停止瞭解這個問題。祝你好運,歡呼。 – Simon

1

你可以嘗試使用mp4box來重構你的文件。 moov框給出了每個音頻和視頻樣本的索引。如果該文件位於文件末尾,則很難傳輸。

這可能幫助: http://boliston.wordpress.com/tag/moov-box/

或者這樣: mp4box -inter 0.5 some_file.mp4

(我沒有目前有嘗試的機會),如果您需要這

與您的應用程序一起工作,我不知道任何將mp4box移植到Android的活動。

+0

BTW mp4box是GPAC項目的一部分。至少在Ubuntu中有一個包。 http://gpac.wp.mines-telecom.fr/ –

0

我今天嘗試做同樣的事情,但mp4不是很容易流(如前所述,一些部分寫在最後)。我沒有說這是不可能的,但似乎至少很難。

因此,解決更新的Android API(4。3)可能是這一個:

  • 將相機預覽到表面紋理:camera.setPreviewTexture
  • 記錄此紋理使用OpenGL和MediaCodex +複用器

這種解決方案的缺點是相機的預覽大小可能小於視頻大小。這意味着取決於您的設備,您無法以最高分辨率錄製。提示:有些相機說他們不支持更高的預覽尺寸,但是他們可以,並且您可以嘗試配置相機以將預覽尺寸設置爲視頻尺寸。如果這樣做,請捕獲camera.setParameters的RuntimeException,如果失敗,則只使用支持的預覽大小。

一些鏈接如何從表面紋理記錄:

Bigflage: great examples for MediaCodec stuff.

The VideoRecorder class from Lablet.

也可能是有用的:spydroid-IPCAMERA從MediaRecorder插座爲RTP流流中的數據,但我沒有發現任何將其提供給MediaCodec的方法。 (我已經被困在讀取正確的NAL單元大小,因爲他們這樣做...)