2012-05-23 14 views
6

Próbuję wysłać wideo h264/AAC z MediaRecorder Android przez lokalny Socket. Celem jest wysłanie wideo na serwer WOWZA za pośrednictwem RTMP lub RTSP, ale daje mi to wiele problemów i na razie próbuję tylko zapisać dane do pliku z LocalServerSocket.Przesyłanie strumieniowe wideo z MediaRecorder poprzez LocalSocket

Oto kod. Przepraszam, że to nie jest naprawdę czyste, ale spędziłem wiele godzin na testowaniu wielu rzeczy, a mój projekt jest teraz bałagan.

W działalności Camera setup plik wyjściowy:

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

Realizacja 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) {} 
    } 
} 

Problemem jest to, że plik wynikająca z tego nie jest czytelny dla dowolnego odtwarzacza multimedialnego. Czy uważasz, że dzieje się tak z powodu problemu z kodowaniem? Ten kod powinien wygenerować plik binarny, jeśli dobrze rozumiem ?!

Z góry dziękuję, pozdrawiam.

+0

jeśli nie dostaniesz błędów to prawdopodobnie jest spowodowane problemami z kodowaniem/nazwami plików. Co [OutputFormat] (http://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html) ustawiłeś? Może zmiana nazwy na '.3gp' lub tak pomaga - patrz [tutaj] (http://stackoverflow.com/questions/9110711/android-mediarecorder-getting-3gp-instead-of-mpeg4) – zapl

+0

Format wyjściowy to MPEG_4, więc myślę, że powinno to być ok z rozszerzeniem .mp4. Poza tym, jeśli piszę bezpośrednio do pliku .mp4 w mMediaRecorder.setOutputFile(), to działa idealnie. – Simon

+0

czy sprawdziłeś, czy coś takiego jak [mediainfo] (http://mediainfo.sourceforge.net/en) może odczytać właściwości stworzonego wideo? Możesz także wypróbować różnicę binarną (przynajmniej nagłówek) bezpośrednio wygenerowanego pliku i plik wysłać przez lokalne gniazdo, aby sprawdzić, czy wygenerowany plik wygląda prawidłowo. – zapl

Odpowiedz

2

Ok, Znalazłem, dlaczego pliki nie mogły zostać odtworzone. W MP4 i 3GPP plików, nie ma nagłówek zawierający bajtów:

ftyp3gp4 3gp43gp6 szeroki MDAT

w HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

Te 4 bajty przed Znacznik "mdat" reprezentuje pozycję innego znacznika "moov" znajdującego się w koniec pliku. Pozycja jest zwykle ustawiana po zakończeniu nagrywania, ale ponieważ MediaRecorder nie może wyszukać gniazd, nie może ustawić tych bajtów na prawidłową wartość w naszym przypadku.

Mój problem polega na tym, aby znaleźć sposób na przesłanie takiego pliku, ponieważ wymaga on odtworzenia przed zakończeniem nagrywania.

+3

Czy znalazłeś rozwiązanie, które sprawi, że będzie można go przesyłać strumieniowo? – Houf

+0

Cześć Simon, Znalazłeś jakieś rozwiązanie .. proszę, podziel się tym, utknąłem w tym samym numerze –

+0

Cześć Ankita. Przepraszamy, ale na razie opuściliśmy projekt, więc przestałem pracować nad tym problemem. Powodzenia w tym, okrzyki. – Simon

1

Możesz spróbować użyć mp4box do restrukturyzacji pliku. Pole moov podaje indeksy dla każdej próbki audio i wideo. Jeśli znajduje się na końcu pliku, utrudnia przesyłanie strumieniowe.

To może pomóc: http://boliston.wordpress.com/tag/moov-box/

albo to: mp4box -inter 0,5 some_file.mp4

(nie mam okazję spróbować obecnie)

Jeśli trzeba to Współpracuję z Twoją aplikacją, nie jestem świadomy żadnych działań związanych z portem mp4box na Androida.

+0

BTW mp4box jest obecnie częścią projektu GPAC. W systemie Ubuntu jest przynajmniej taki pakiet. http://gpac.wp.mines-telecom.fr/ –

0

Próbowałem dzisiaj zrobić to samo, ale mp4 nie jest łatwe do streamowania (jak powiedzieliśmy przed napisaniem niektórych części na końcu). Nie mówię, że to niemożliwe, ale wydaje się co najmniej dość trudne.

Tak więc obejście dla nowszych interfejsów API Androida (4.3) może być to jedno:

  • Ustaw podgląd kamery do SurfaceTexture: camera.setPreviewTexture
  • Record to tekstury przy użyciu OpenGL i MediaCodex + muxer

Wadą tego rozwiązania jest to, że Rozmiar podglądu kamery może być mniejszy niż rozmiar wideo. Oznacza to, że w zależności od urządzenia nie można nagrywać z najwyższą rozdzielczością. Podpowiedź: niektóre aparaty mówią, że nie obsługują większych rozmiarów podglądu, ale robią to i można spróbować skonfigurować aparat, aby ustawić rozmiar podglądu na rozmiar wideo. W takim przypadku należy uchwycić wyjątek RuntimeException camera.setParameters, a jeśli się nie uda, należy użyć obsługiwanych rozmiarów podglądu.

Niektóre linki Jak nagrywać z SurfaceTexture:

Bigflage: great examples for MediaCodec stuff.

The VideoRecorder class from Lablet.

Może być również przydatne: spydroid-ipcamera strumieni danych z gniazda MediaRecorder jako strumienie RTP ale znalazłem nie sposób na przekazanie tego do MediaCodec. (Już utknąłem czytając poprawne rozmiary jednostek NAL, tak jak robią ...)

Powiązane problemy