From 1e5c7c167552276328275ea4da797720a0687be7 Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Sat, 17 Jun 2017 10:12:22 +0800 Subject: [PATCH 1/9] Fix NDK r15 undeclared identifier Signed-off-by: Leo Ma --- app/build.gradle | 2 +- build.gradle | 2 +- library/build.gradle | 2 +- library/src/main/cpp/libenc/libenc.cc | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3529770..c9cbad4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,7 @@ android { minSdkVersion 16 targetSdkVersion 22 versionCode 1 - versionName "2.5" + versionName "2.6" ndk { abiFilters "armeabi-v7a", "x86" } diff --git a/build.gradle b/build.gradle index 3a56163..6514a0b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/library/build.gradle b/library/build.gradle index 62a2302..fa4bb22 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -8,7 +8,7 @@ android { minSdkVersion 16 targetSdkVersion 22 versionCode 1 - versionName "2.5" + versionName "2.6" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { diff --git a/library/src/main/cpp/libenc/libenc.cc b/library/src/main/cpp/libenc/libenc.cc index 813ffef..85ad3d3 100644 --- a/library/src/main/cpp/libenc/libenc.cc +++ b/library/src/main/cpp/libenc/libenc.cc @@ -1,9 +1,10 @@ #include - -#include +#include #include #include +#include + #define LIBENC_LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "libenc", __VA_ARGS__)) #define LIBENC_LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO , "libenc", __VA_ARGS__)) #define LIBENC_LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN , "libenc", __VA_ARGS__)) From 9f4e11430826c7bb57f361890df62f0b4d47eb5f Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Mon, 26 Jun 2017 10:37:34 +0800 Subject: [PATCH 2/9] Parameter adjustment Signed-off-by: Leo Ma --- .../main/java/net/ossrs/yasea/SrsEncoder.java | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/library/src/main/java/net/ossrs/yasea/SrsEncoder.java b/library/src/main/java/net/ossrs/yasea/SrsEncoder.java index 807798d..fca54b8 100644 --- a/library/src/main/java/net/ossrs/yasea/SrsEncoder.java +++ b/library/src/main/java/net/ossrs/yasea/SrsEncoder.java @@ -26,18 +26,18 @@ public class SrsEncoder { public static String x264Preset = "veryfast"; public static int vPrevWidth = 640; public static int vPrevHeight = 360; - public static int vPortraitWidth = 720; - public static int vPortraitHeight = 1280; - public static int vLandscapeWidth = 1280; - public static int vLandscapeHeight = 720; - public static int vOutWidth = 720; // Note: the stride of resolution must be set as 16x for hard encoding with some chip like MTK - public static int vOutHeight = 1280; // Since Y component is quadruple size as U and V component, the stride must be set as 32x + public static int vPortraitWidth = 360; + public static int vPortraitHeight = 640; + public static int vLandscapeWidth = 640; + public static int vLandscapeHeight = 360; + public static int vOutWidth = 360; // Note: the stride of resolution must be set as 16x for hard encoding with some chip like MTK + public static int vOutHeight = 640; // Since Y component is quadruple size as U and V component, the stride must be set as 32x public static int vBitrate = 1200 * 1024; // 1200 kbps public static final int VFPS = 24; public static final int VGOP = 48; public static final int ASAMPLERATE = 44100; public static int aChannelConfig = AudioFormat.CHANNEL_IN_STEREO; - public static final int ABITRATE = 128 * 1024; // 128 kbps + public static final int ABITRATE = 64 * 1024; // 64 kbps private SrsEncodeHandler mHandler; @@ -340,26 +340,31 @@ public class SrsEncoder { } public void onGetPcmFrame(byte[] data, int size) { - ByteBuffer[] inBuffers = aencoder.getInputBuffers(); - ByteBuffer[] outBuffers = aencoder.getOutputBuffers(); - - int inBufferIndex = aencoder.dequeueInputBuffer(-1); - if (inBufferIndex >= 0) { - ByteBuffer bb = inBuffers[inBufferIndex]; - bb.clear(); - bb.put(data, 0, size); - long pts = System.nanoTime() / 1000 - mPresentTimeUs; - aencoder.queueInputBuffer(inBufferIndex, 0, size, pts, 0); - } + // Check video frame cache number to judge the networking situation. + // Just cache GOP / FPS seconds data according to latency. + AtomicInteger videoFrameCacheNumber = flvMuxer.getVideoFrameCacheNumber(); + if (videoFrameCacheNumber != null && videoFrameCacheNumber.get() < VGOP) { + ByteBuffer[] inBuffers = aencoder.getInputBuffers(); + ByteBuffer[] outBuffers = aencoder.getOutputBuffers(); + + int inBufferIndex = aencoder.dequeueInputBuffer(-1); + if (inBufferIndex >= 0) { + ByteBuffer bb = inBuffers[inBufferIndex]; + bb.clear(); + bb.put(data, 0, size); + long pts = System.nanoTime() / 1000 - mPresentTimeUs; + aencoder.queueInputBuffer(inBufferIndex, 0, size, pts, 0); + } - for (; ; ) { - int outBufferIndex = aencoder.dequeueOutputBuffer(aebi, 0); - if (outBufferIndex >= 0) { - ByteBuffer bb = outBuffers[outBufferIndex]; - onEncodedAacFrame(bb, aebi); - aencoder.releaseOutputBuffer(outBufferIndex, false); - } else { - break; + for (; ; ) { + int outBufferIndex = aencoder.dequeueOutputBuffer(aebi, 0); + if (outBufferIndex >= 0) { + ByteBuffer bb = outBuffers[outBufferIndex]; + onEncodedAacFrame(bb, aebi); + aencoder.releaseOutputBuffer(outBufferIndex, false); + } else { + break; + } } } } From a8c36e3b43a1fd4bb4dace538d7b46873dca68f9 Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Mon, 26 Jun 2017 10:38:34 +0800 Subject: [PATCH 3/9] Parameter adjustment Signed-off-by: Leo Ma --- app/src/main/java/net/ossrs/yasea/demo/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/ossrs/yasea/demo/MainActivity.java b/app/src/main/java/net/ossrs/yasea/demo/MainActivity.java index 48cd1c8..53b34ac 100644 --- a/app/src/main/java/net/ossrs/yasea/demo/MainActivity.java +++ b/app/src/main/java/net/ossrs/yasea/demo/MainActivity.java @@ -72,7 +72,7 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL mPublisher.setRtmpHandler(new RtmpHandler(this)); mPublisher.setRecordHandler(new SrsRecordHandler(this)); mPublisher.setPreviewResolution(640, 360); - mPublisher.setOutputResolution(720, 1280); + mPublisher.setOutputResolution(360, 640); mPublisher.setVideoHDMode(); mPublisher.startCamera(); From f759800d87eae363807d094025c676f6e250545e Mon Sep 17 00:00:00 2001 From: vkuzub Date: Wed, 28 Jun 2017 16:20:49 +0300 Subject: [PATCH 4/9] Added startTorch and stopTorch methods (#462) --- .../java/net/ossrs/yasea/SrsCameraView.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/src/main/java/net/ossrs/yasea/SrsCameraView.java b/library/src/main/java/net/ossrs/yasea/SrsCameraView.java index 696b787..de3d5ee 100644 --- a/library/src/main/java/net/ossrs/yasea/SrsCameraView.java +++ b/library/src/main/java/net/ossrs/yasea/SrsCameraView.java @@ -191,6 +191,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render } public void setCameraId(int id) { + stopTorch(); mCamId = id; setPreviewOrientation(mPreviewOrientation); } @@ -320,6 +321,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render public void stopCamera() { disableEncoding(); + stopTorch(); if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); @@ -388,6 +390,29 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render return closestRange; } + public boolean startTorch() { + if (mCamera != null) { + Camera.Parameters params = mCamera.getParameters(); + List supportedFlashModes = params.getSupportedFlashModes(); + if (supportedFlashModes != null && !supportedFlashModes.isEmpty()) { + if (supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) { + params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + mCamera.setParameters(params); + return true; + } + } + } + return false; + } + + public void stopTorch() { + if (mCamera != null) { + Camera.Parameters params = mCamera.getParameters(); + params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + mCamera.setParameters(params); + } + } + public interface PreviewCallback { void onGetRgbaFrame(byte[] data, int width, int height); From f6dfbe3f6277de6e10e2388382152202c413c233 Mon Sep 17 00:00:00 2001 From: begeekmyfriend Date: Thu, 29 Jun 2017 21:57:55 +0800 Subject: [PATCH 5/9] Fix audio sampling in FLV muxer Signed-off-by: begeekmyfriend # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Your branch is up-to-date with 'origin/master'. # # Changes to be committed: # modified: library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java # --- .../java/net/ossrs/yasea/SrsFlvMuxer.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java index 1508b20..f29b994 100644 --- a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java +++ b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java @@ -343,13 +343,12 @@ public class SrsFlvMuxer { */ private class SrsCodecAudioSampleRate { - // set to the max value to reserved, for array map. - public final static int Reserved = 4; - - public final static int R5512 = 0; - public final static int R11025 = 1; - public final static int R22050 = 2; - public final static int R44100 = 3; + public final static int R5512 = 5512; + public final static int R11025 = 11025; + public final static int R22050 = 22050; + public final static int R44100 = 44100; + public final static int R32000 = 32000; + public final static int R16000 = 16000; } /** @@ -749,6 +748,10 @@ public class SrsFlvMuxer { samplingFrequencyIndex = 0x07; } else if (asample_rate == SrsCodecAudioSampleRate.R11025) { samplingFrequencyIndex = 0x0a; + } else if (asample_rate == SrsCodecAudioSampleRate.R32000) { + samplingFrequencyIndex = 0x05; + } else if (asample_rate == SrsCodecAudioSampleRate.R16000) { + samplingFrequencyIndex = 0x08; } ch |= (samplingFrequencyIndex >> 1) & 0x07; audio_tag.put(ch, 2); @@ -787,11 +790,13 @@ public class SrsFlvMuxer { sound_type = 1; // 1 = Stereo sound } byte sound_size = 1; // 1 = 16-bit samples - byte sound_rate = 3; // 44100, 22050, 11025 + byte sound_rate = 3; // 44100, 22050, 11025, 5512 if (asample_rate == 22050) { sound_rate = 2; } else if (asample_rate == 11025) { sound_rate = 1; + } else if (asample_rate == 5512) { + sound_rate = 0; } // for audio frame, there is 1 or 2 bytes header: From 98afa75c65be94abef3297b678f20717075cb0a4 Mon Sep 17 00:00:00 2001 From: Moo Date: Tue, 18 Jul 2017 12:05:03 +0800 Subject: [PATCH 6/9] add proguard for release build --- proguard-rules.pro | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 proguard-rules.pro diff --git a/proguard-rules.pro b/proguard-rules.pro new file mode 100644 index 0000000..cc90e0e --- /dev/null +++ b/proguard-rules.pro @@ -0,0 +1,2 @@ +-keep class net.ossrs.yasea.**{*;} +-keep class net.ossrs.yasea.SrsEncoder{*;} From 88dd496f1a411cf52b1247b0bd87e59e7398a96b Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Wed, 19 Jul 2017 17:00:59 +0800 Subject: [PATCH 7/9] Disable multi-slice for iOS HW decoding Signed-off-by: Leo Ma --- library/src/main/cpp/libenc/libenc.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/src/main/cpp/libenc/libenc.cc b/library/src/main/cpp/libenc/libenc.cc index 85ad3d3..65ce45e 100644 --- a/library/src/main/cpp/libenc/libenc.cc +++ b/library/src/main/cpp/libenc/libenc.cc @@ -516,6 +516,8 @@ static jboolean libenc_openSoftEncoder(JNIEnv *env, jobject thiz) { x264_param_default_preset(&x264_ctx.params, x264_ctx.preset, "zerolatency"); x264_ctx.params.b_repeat_headers = 0; + // for iOS HW decoding + x264_ctx.params.b_sliced_threads = 0; x264_ctx.global_nal_header = true; // resolution From da8ca49ebb72265d92dc6cb9dfb681d16f763dd4 Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Thu, 10 Aug 2017 14:08:38 +0800 Subject: [PATCH 8/9] Ignore annexb exception processing Some devices produce unstandard H.264 slice without startcode. So we ignore the annexb exception processing since it does not matter for streaming. Signed-off-by: Leo Ma --- .../java/net/ossrs/yasea/SrsFlvMuxer.java | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java index f29b994..855c185 100644 --- a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java +++ b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java @@ -634,38 +634,27 @@ public class SrsFlvMuxer { } public SrsFlvFrameBytes demuxAnnexb(ByteBuffer bb, MediaCodec.BufferInfo bi) { - SrsFlvFrameBytes tbb = new SrsFlvFrameBytes(); + // each frame must prefixed by annexb format. + // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + SrsAnnexbSearch tbbsc = searchAnnexb(bb, bi); + // the start codes. + for (int i = 0; i < tbbsc.nb_start_code; i++) { + bb.get(); + } + // find out the frame size. + SrsFlvFrameBytes tbb = new SrsFlvFrameBytes(); + tbb.data = bb.slice(); + int pos = bb.position(); while (bb.position() < bi.size) { - // each frame must prefixed by annexb format. - // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. - SrsAnnexbSearch tbbsc = searchAnnexb(bb, bi); - if (!tbbsc.match || tbbsc.nb_start_code < 3) { - Log.e(TAG, "annexb not match."); - mHandler.notifyRtmpIllegalArgumentException(new IllegalArgumentException( - String.format("annexb not match for %dB, pos=%d", bi.size, bb.position()))); - } - - // the start codes. - for (int i = 0; i < tbbsc.nb_start_code; i++) { - bb.get(); - } - - // find out the frame size. - tbb.data = bb.slice(); - int pos = bb.position(); - while (bb.position() < bi.size) { - SrsAnnexbSearch bsc = searchAnnexb(bb, bi); - if (bsc.match) { - break; - } - bb.get(); + SrsAnnexbSearch bsc = searchAnnexb(bb, bi); + if (bsc.match) { + break; } - - tbb.size = bb.position() - pos; - break; + bb.get(); } + tbb.size = bb.position() - pos; return tbb; } } From 84b10e18709629d90fef67a49df71581a4091369 Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Thu, 10 Aug 2017 17:58:03 +0800 Subject: [PATCH 9/9] Annexb search optimization Assume there always be single slice for each video frame when sps and pps are found. That would promote efficiency on some low-end devices. Signed-off-by: Leo Ma --- .../java/net/ossrs/yasea/SrsFlvMuxer.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java index 855c185..50ec78a 100644 --- a/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java +++ b/library/src/main/java/net/ossrs/yasea/SrsFlvMuxer.java @@ -456,6 +456,11 @@ public class SrsFlvMuxer { private SrsFlvFrameBytes sps_bb = new SrsFlvFrameBytes(); private SrsFlvFrameBytes pps_hdr = new SrsFlvFrameBytes(); private SrsFlvFrameBytes pps_bb = new SrsFlvFrameBytes(); + private boolean sps_pps_found = false; + + public void reset() { + sps_pps_found = false; + } public boolean isSps(SrsFlvFrameBytes frame) { return frame.size >= 1 && (frame.data.get(0) & 0x1f) == SrsAvcNaluType.SPS; @@ -569,6 +574,8 @@ public class SrsFlvMuxer { pps_bb.size = pps.array().length; pps_bb.data = pps.duplicate(); frames.add(pps_bb); + + sps_pps_found = true; } public SrsAllocator.Allocation muxFlvTag(ArrayList frames, int frame_type, @@ -645,16 +652,23 @@ public class SrsFlvMuxer { // find out the frame size. SrsFlvFrameBytes tbb = new SrsFlvFrameBytes(); tbb.data = bb.slice(); - int pos = bb.position(); - while (bb.position() < bi.size) { - SrsAnnexbSearch bsc = searchAnnexb(bb, bi); - if (bsc.match) { - break; + + // Assume there always be single slice for each video frame when sps and pps are found. + // That would promote efficiency on some low-end devices. + if (sps_pps_found) { + tbb.size = bi.size - bb.position(); + bb.position(bb.limit()); + } else { + int pos = bb.position(); + while (bb.position() < bi.size) { + SrsAnnexbSearch bsc = searchAnnexb(bb, bi); + if (bsc.match) { + break; + } + bb.get(); } - bb.get(); + tbb.size = bi.size - pos; } - - tbb.size = bb.position() - pos; return tbb; } } @@ -705,6 +719,7 @@ public class SrsFlvMuxer { h264_pps_changed = false; h264_sps_pps_sent = false; aac_specific_config_got = false; + avc.reset(); } public void setVideoTrack(MediaFormat format) { @@ -851,7 +866,7 @@ public class SrsFlvMuxer { // 5bits, 7.3.1 NAL unit syntax, // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame - int nal_unit_type = (int)(frame.data.get(0) & 0x1f); + int nal_unit_type = frame.data.get(0) & 0x1f; if (nal_unit_type == SrsAvcNaluType.SPS || nal_unit_type == SrsAvcNaluType.PPS) { Log.i(TAG, String.format("annexb demux %dB, pts=%d, frame=%dB, nalu=%d", bi.size, pts, frame.size, nal_unit_type));