libstreaming adalah API yang memungkinkan Anda, hanya dengan beberapa baris kode, melakukan streaming kamera dan/atau mikrofon perangkat bertenaga Android menggunakan RTP melalui UDP.
Langkah pertama yang perlu Anda lakukan untuk memulai sesi streaming ke beberapa rekan disebut 'memberi sinyal'. Selama langkah ini Anda akan menghubungi penerima dan mengirimkan deskripsi aliran masuk. Anda memiliki tiga cara untuk melakukannya dengan libstreaming.
Dokumentasi javadoc lengkap tentang API tersedia di sini: http://guigui.us/libstreaming/doc
Ada tiga cara di Android untuk mendapatkan data yang dikodekan dari periferal:
API MediaRecorder tidak dimaksudkan untuk aplikasi streaming tetapi dapat digunakan untuk mengambil data yang disandikan dari periferal telepon. Caranya adalah dengan mengonfigurasi instance MediaRecorder untuk menulis ke LocalSocket, bukan file biasa (lihat MediaStream.java ).
Sunting: pada Android Lollipop menggunakan LocalSocket tidak dimungkinkan lagi karena alasan keamanan. Namun menggunakan ParcelFileDescriptor berhasil. Lebih detailnya ada di file MediaStream.java ! (Terima kasih kepada orang-orang itu atas wawasannya)
Peretasan ini memiliki beberapa batasan:
Sulit untuk mengatakan seberapa baik peretasan ini akan bekerja pada ponsel. Ini berfungsi dengan baik di banyak perangkat.
MediaCodec API tidak menghadirkan batasan yang baru saja saya sebutkan, tetapi memiliki masalahnya sendiri. Sebenarnya ada dua cara untuk menggunakan MediaCodec API: dengan buffer atau dengan permukaan.
Metode buffer-to-buffer menggunakan panggilan ke dequeueInputBuffer dan [ queueInputBuffer ](http://developer.android.com/reference/android/media/MediaCodec.html#queueInputBuffer(int, int, int, long, int)) ke memberi makan encoder dengan data mentah. Tampaknya mudah bukan? Sebenarnya tidak, karena pembuat enkode video yang dapat Anda akses dengan API ini menggunakan format warna berbeda dan Anda harus mendukung semuanya. Daftar format warna tersebut tersedia di sini. Selain itu, banyak pembuat enkode yang mengklaim dukungan untuk format warna yang sebenarnya tidak mereka dukung dengan baik atau dapat menimbulkan sedikit gangguan.
Semua paket hw didedikasikan untuk menyelesaikan masalah tersebut. Lihat khususnya kelas EncoderDebugger .
Jika streaming dengan API tersebut gagal, libstreaming melakukan fallback pada streaming dengan MediaRecorder API .
Metode permukaan-ke-buffer menggunakan metode createInputSurface(). Metode ini mungkin merupakan cara terbaik untuk menyandikan video mentah dari kamera tetapi memerlukan Android 4.3 dan lebih tinggi.
Paket gl didedikasikan untuk menggunakan MediaCodec API dengan permukaan.
Ini belum diaktifkan secara default di libstreaming tetapi Anda dapat memaksanya dengan metode setStreamingMethod(byte) .
Setelah data mentah dari periferal dikodekan, data tersebut dienkapsulasi dalam aliran RTP yang sesuai. Algoritme paketisasi yang harus digunakan bergantung pada format data (H.264, H.263, AMR dan AAC) dan semuanya ditentukan dalam RFC masing-masing:
Jika Anda mencari implementasi dasar dari salah satu RFC yang disebutkan di atas, periksa sumber dari kelas yang sesuai.
Paket RTCP juga dikirim ke penerima sejak libstreaming versi 2.0. Hanya Laporan Pengirim yang diterapkan. Mereka sebenarnya diperlukan untuk sinkronisasi bibir.
Paket rtp menangani paketisasi data yang dikodekan dalam paket RTP.
< uses-permission android : name = " android.permission.INTERNET " />
< uses-permission android : name = " android.permission.WRITE_EXTERNAL_STORAGE " />
< uses-permission android : name = " android.permission.RECORD_AUDIO " />
< uses-permission android : name = " android.permission.CAMERA " />
Contoh ini diambil dari aplikasi android sederhana ini. Ini bisa menjadi bagian dari Aktivitas, Fragmen, atau Layanan.
protected void onCreate ( Bundle savedInstanceState ) {
...
mSession = SessionBuilder . getInstance ()
. setCallback ( this )
. setSurfaceView ( mSurfaceView )
. setPreviewOrientation ( 90 )
. setContext ( getApplicationContext ())
. setAudioEncoder ( SessionBuilder . AUDIO_NONE )
. setAudioQuality ( new AudioQuality ( 16000 , 32000 ))
. setVideoEncoder ( SessionBuilder . VIDEO_H264 )
. setVideoQuality ( new VideoQuality ( 320 , 240 , 20 , 500000 ))
. build ();
mSurfaceView . getHolder (). addCallback ( this );
...
}
public void onPreviewStarted () {
Log . d ( TAG , "Preview started." );
}
@ Override
public void onSessionConfigured () {
Log . d ( TAG , "Preview configured." );
// Once the stream is configured, you can get a SDP formated session description
// that you can send to the receiver of the stream.
// For example, to receive the stream in VLC, store the session description in a .sdp file
// and open it with VLC while streming.
Log . d ( TAG , mSession . getSessionDescription ());
mSession . start ();
}
@ Override
public void onSessionStarted () {
Log . d ( TAG , "Streaming session started." );
...
}
@ Override
public void onSessionStopped () {
Log . d ( TAG , "Streaming session stopped." );
...
}
@ Override
public void onBitrateUpdate ( long bitrate ) {
// Informs you of the bandwidth consumption of the streams
Log . d ( TAG , "Bitrate: " + bitrate );
}
@ Override
public void onSessionError ( int message , int streamType , Exception e ) {
// Might happen if the streaming at the requested resolution is not supported
// or if the preview surface is not ready...
// Check the Session class for a list of the possible errors.
Log . e ( TAG , "An error occured" , e );
}
@ Override
public void surfaceChanged ( SurfaceHolder holder , int format , int width ,
int height ) {
}
@ Override
public void surfaceCreated ( SurfaceHolder holder ) {
// Starts the preview of the Camera
mSession . startPreview ();
}
@ Override
public void surfaceDestroyed ( SurfaceHolder holder ) {
// Stops the streaming session
mSession . stop ();
}
SessionBuilder hanya memfasilitasi pembuatan objek Session . Panggilan ke setSurfaceView diperlukan untuk streaming video, hal ini seharusnya tidak mengejutkan karena Android memerlukan permukaan yang valid untuk merekam video (ini adalah batasan yang mengganggu dari MediaRecorder API). Di Android 4.3, streaming tanpa SurfaceView dapat dilakukan tetapi belum diterapkan. Panggilan ke setContext(Context) diperlukan, ini memungkinkan objek H264Stream dan objek AACStream menyimpan dan memulihkan data menggunakan SharedPreferences .
Objek Sesi mewakili sesi streaming ke beberapa rekan. Ini berisi satu atau lebih objek Stream yang dimulai (resp.stop) ketika metode start() (resp.stop () ) dipanggil.
Metode getSessionDescription() akan mengembalikan SDP sesi dalam bentuk String. Sebelum memanggilnya, Anda harus memastikan bahwa Sesi telah dikonfigurasi. Setelah memanggil konfig() atau startPreview() pada instance Sesi Anda, panggilan balik onSessionConfigured() akan dipanggil.
Dalam contoh yang disajikan di atas, instance Sesi digunakan secara asinkron dan panggilan ke metodenya tidak diblokir. Anda tahu kapan sesuatu selesai ketika panggilan balik dipanggil.
Anda juga dapat menggunakan objek Session secara sinkron seperti itu:
// Blocks until the all streams are configured
try {
mSession . syncConfigure ();
} catch ( Exception e ) {
...
}
Strinf sdp = mSession . getSessionDescription ();
...
// Blocks until streaming actually starts.
try {
mSession . syncStart ();
} catch ( Exception e ) {
...
}
...
mSession . syncStop ();
Lihat halaman wiki ini dan contoh 3.
< service android : name = " net.majorkernelpanic.streaming.rtsp.RtspServer " />
Jika Anda memutuskan untuk mengganti RtspServer, ubah baris di atas.
Editor editor = PreferenceManager . getDefaultSharedPreferences ( this ). edit ();
editor . putString ( RtspServer . KEY_PORT , String . valueOf ( 1234 ));
editor . commit ();
Port memang disimpan sebagai String di preferensi, ada alasan bagus untuk itu. Objek EditTextPreference menyimpan inputnya sebagai String dan tidak dapat dengan mudah (seseorang perlu menggantinya) dikonfigurasi untuk menyimpannya sebagai Integer.
SessionBuilder . getInstance ()
. setSurfaceHolder ( mSurfaceView . getHolder ())
. setContext ( getApplicationContext ())
. setAudioEncoder ( SessionBuilder . AUDIO_AAC )
. setVideoEncoder ( SessionBuilder . VIDEO_H264 );
// Starts the RTSP server
context . startService ( new Intent ( this , RtspServer . class ));
// Stops the RTSP server
context . stopService ( new Intent ( this , RtspServer . class ));
Kunjungi halaman github ini untuk melihat bagaimana tumpukan streaming ini dapat digunakan dan kinerjanya.