2012-05-23 34 views
6

Sto provando a inviare video h264/AAC da MediaRecorder di Android tramite un socket locale. L'obiettivo è quello di inviare video a un server WOWZA tramite RTMP o RTSP, ma mi dà un sacco di problemi e per ora sto solo cercando di scrivere i dati su un file dal LocalServerSocket.Streaming video da MediaRecorder tramite LocalSocket

Ecco un codice. Spiacente, non è molto pulito, ma ho passato ore a testare molte cose e il mio progetto è un casino in questo momento.

Nell'attività fotocamera, l'impostazione del file di output:

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()); 

L'implementazione 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) {} 
    } 
} 

Il problema è che il file risultante da questo non è leggibile da qualsiasi lettore multimediale. Pensi che questo sia dovuto a un problema di codifica? Questo codice dovrebbe generare un file binario se ho capito bene ?!

Grazie in anticipo, grazie.

+0

se non si verificano errori è probabilmente causato da problemi di codifica/nome file. Cosa [OutputFormat] (http://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html) hai impostato? Forse rinominarlo in '.3gp' o così aiuta - vedi [qui] (http://stackoverflow.com/questions/9110711/android-mediarecorder-getting-3gp-instead-of-mpeg4) – zapl

+0

Il formato di output è MPEG_4, quindi suppongo che dovrebbe andare bene con un'estensione .mp4. Inoltre, se scrivo direttamente in un file .mp4 in mMediaRecorder.setOutputFile() funziona perfettamente. – Simon

+0

hai controllato se qualcosa come [mediainfo] (http://mediainfo.sourceforge.net/en) può leggere le proprietà del video creato? Si potrebbe anche provare un diff binario (almeno dell'intestazione) di un file generato direttamente e un file inviato attraverso il socket locale per verificare se il file generato sembra corretto. – zapl

risposta

2

Ok, ho trovato il motivo per cui i file non potevano essere riprodotti. In file MP4 e 3GPP, c'è un'intestazione contenente il byte:

ftyp3gp4 3gp43gp6 vasta mdat

in HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

I 4 byte prima della Il tag 'mdat' rappresenta la posizione di un altro tag 'moov' situato al fine del file. La posizione viene solitamente impostata quando la registrazione è terminata, ma poiché MediaRecorder non può cercare socket, non è possibile impostare questi byte sul valore corretto nel nostro caso.

Il mio problema ora è trovare un modo per rendere un file di questo tipo riproducibile in streaming, dal momento che è necessario riprodurlo prima che la registrazione sia terminata.

+3

Hai trovato una soluzione per renderla scorrevole? – Houf

+0

Ciao Simon, hai trovato qualche soluzione ... per favore, condividilo, sto stucchiando nello stesso numero –

+0

Ciao Ankita. Scusate ma per il momento abbiamo abbandonato il progetto, quindi ho smesso di lavorare su questo problema. Buona fortuna con questo, grazie. – Simon

1

Si potrebbe provare a utilizzare mp4box per ristrutturare il file. La finestra moov fornisce gli indici per ciascun campione audio e video. Se questo è alla fine del file, rende difficile lo streaming.

Questo potrebbe aiutare: http://boliston.wordpress.com/tag/moov-box/

O questo: MP4Box -inter 0,5 some_file.mp4

(non ho la possibilità di provare al momento)

Se avete bisogno di questo per funziona con la tua app, non sono a conoscenza di attività per portare mp4box ad Android.

+0

BTW mp4box fa parte del progetto GPAC al giorno d'oggi. C'è un pacchetto per questo in Ubuntu, almeno. http://gpac.wp.mines-telecom.fr/ –

0

Ho provato oggi a fare lo stesso, ma mp4 non è molto facile da riprodurre in streaming (come detto prima alcune parti sono scritte alla fine). Non dico che sia impossibile ma sembra almeno abbastanza difficile.

Quindi una soluzione per le nuove API Android (4.3) potrebbe essere questa:

  • Impostare la fotocamera anteprima per un SurfaceTexture: camera.setPreviewTexture
  • Record questa texture utilizzando OpenGL e MediaCodex + Muxer

Lo svantaggio di questa soluzione è che il le dimensioni di anteprima di una fotocamera potrebbero essere inferiori alle dimensioni del video. Ciò significa che a seconda del tuo dispositivo non puoi registrare alla massima risoluzione. Suggerimento: alcune fotocamere dicono che non supportano dimensioni di anteprima più elevate, ma lo fanno e puoi provare a configurare la videocamera per impostare le dimensioni dell'anteprima sulla dimensione del video. Se lo fai, prendi la RuntimeException di camera.setParameters e, se fallisce, usa solo le dimensioni di anteprima supportate.

Alcuni link Come registrare da un SurfaceTexture:

Bigflage: great examples for MediaCodec stuff.

The VideoRecorder class from Lablet.

Può anche essere utile: spydroid-ipcamera flussi di dati dalla presa MediaRecorder come flussi RTP, ma non ho trovato modo per nutrirlo con MediaCodec. (Ho già bloccato leggendo le dimensioni dell'unità NAL corrette come fanno ...)