├── x264-codec
├── .gitignore
├── consumer-rules.pro
├── src
│ ├── main
│ │ ├── jni
│ │ │ ├── Android.mk
│ │ │ ├── Application.mk
│ │ │ ├── fdkaac
│ │ │ │ ├── lib
│ │ │ │ │ ├── x86
│ │ │ │ │ │ └── libfdk-aac.a
│ │ │ │ │ └── arm64-v8a
│ │ │ │ │ │ └── libfdk-aac.a
│ │ │ │ └── Android.mk
│ │ │ ├── libx264
│ │ │ │ ├── libs
│ │ │ │ │ ├── x86
│ │ │ │ │ │ └── libx264.a
│ │ │ │ │ ├── x86_64
│ │ │ │ │ │ └── libx264.a
│ │ │ │ │ └── arm64-v8a
│ │ │ │ │ │ └── libx264.a
│ │ │ │ ├── include
│ │ │ │ │ └── x264_config.h
│ │ │ │ └── Android.mk
│ │ │ ├── libopenh264
│ │ │ │ ├── libs
│ │ │ │ │ ├── x86
│ │ │ │ │ │ └── libopenh264.a
│ │ │ │ │ └── arm64-v8a
│ │ │ │ │ │ └── libopenh264.a
│ │ │ │ └── include
│ │ │ │ │ └── wels
│ │ │ │ │ ├── codec_ver.h
│ │ │ │ │ └── codec_def.h
│ │ │ ├── librtmp
│ │ │ │ ├── librtmp.pc.in
│ │ │ │ ├── Android.mk
│ │ │ │ ├── http.h
│ │ │ │ ├── log.h
│ │ │ │ ├── bytes.h
│ │ │ │ ├── rtmp_sys.h
│ │ │ │ ├── log.c
│ │ │ │ ├── amf.h
│ │ │ │ ├── parseurl.c
│ │ │ │ └── librtmp.3
│ │ │ └── softcodec
│ │ │ │ ├── rtmpManage.h
│ │ │ │ ├── Android.mk
│ │ │ │ ├── rtmpManage.c
│ │ │ │ ├── h264_encoder_log.h
│ │ │ │ ├── xiecc_rtmp.h
│ │ │ │ ├── h264Encoder.h
│ │ │ │ ├── aacEncode.h
│ │ │ │ ├── aacEncode.c
│ │ │ │ ├── h264Encoder.c
│ │ │ │ └── xiecc_rtmp.c
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── brucewind
│ │ │ └── softcodec
│ │ │ ├── StreamHelper.java
│ │ │ ├── RtmpHelper.java
│ │ │ └── AudioRecorder.java
│ └── test
│ │ └── java
│ │ └── io
│ │ └── github
│ │ └── brucewind
│ │ └── x264_codec
│ │ └── ExampleUnitTest.java
├── proguard-rules.pro
└── build.gradle
├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ └── activity_main.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── androidyuan
│ │ │ └── ui
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── androidyuan
│ │ │ └── softcodec
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── androidyuan
│ │ └── softcodec
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── openh264-codec
├── .gitignore
├── consumer-rules.pro
├── src
│ ├── main
│ │ ├── jni
│ │ │ ├── Android.mk
│ │ │ ├── Application.mk
│ │ │ ├── softcodec
│ │ │ │ ├── Application.mk
│ │ │ │ ├── print_hex.h
│ │ │ │ ├── rtmpManage.h
│ │ │ │ ├── print_hex.cc
│ │ │ │ ├── Android.mk
│ │ │ │ ├── stdint.h
│ │ │ │ ├── rtmpManage.c
│ │ │ │ ├── h264_encoder_log.h
│ │ │ │ ├── h264Encoder.h
│ │ │ │ ├── xiecc_rtmp.h
│ │ │ │ ├── aacEncode.h
│ │ │ │ └── aacEncode.c
│ │ │ ├── fdkaac
│ │ │ │ ├── lib
│ │ │ │ │ ├── x86
│ │ │ │ │ │ └── libfdk-aac.a
│ │ │ │ │ └── arm64-v8a
│ │ │ │ │ │ └── libfdk-aac.a
│ │ │ │ └── Android.mk
│ │ │ ├── libopenh264
│ │ │ │ ├── libs
│ │ │ │ │ ├── x86
│ │ │ │ │ │ └── libopenh264.a
│ │ │ │ │ └── arm64-v8a
│ │ │ │ │ │ └── libopenh264.a
│ │ │ │ ├── Android.mk
│ │ │ │ └── include
│ │ │ │ │ └── wels
│ │ │ │ │ ├── codec_ver.h
│ │ │ │ │ └── codec_def.h
│ │ │ ├── librtmp
│ │ │ │ ├── librtmp.pc.in
│ │ │ │ ├── Android.mk
│ │ │ │ ├── http.h
│ │ │ │ ├── log.h
│ │ │ │ ├── bytes.h
│ │ │ │ ├── rtmp_sys.h
│ │ │ │ ├── log.c
│ │ │ │ ├── amf.h
│ │ │ │ ├── parseurl.c
│ │ │ │ └── librtmp.3
│ │ │ └── CMakeLists.txt
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── brucewind
│ │ │ └── softcodec
│ │ │ ├── StreamHelper.java
│ │ │ ├── YUVHelper.java
│ │ │ ├── RtmpHelper.java
│ │ │ └── AudioRecorder.java
│ └── test
│ │ └── java
│ │ └── io
│ │ └── github
│ │ └── brucewind
│ │ └── x264_codec
│ │ └── ExampleUnitTest.java
├── README.md
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .github
└── workflows
│ └── build.yml
├── gradle.properties
├── gradlew.bat
├── README_zh_cn.md
├── README.md
├── .gitignore
└── gradlew
/x264-codec/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /obj
--------------------------------------------------------------------------------
/openh264-codec/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/openh264-codec/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/x264-codec/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | include $(call all-subdir-makefiles)
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | //include ':x264-codec'
2 | include ':openh264-codec'
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | include $(call all-subdir-makefiles)
2 |
3 | LOCAL_CPPFLAGS += -O3 -std=c++11
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := arm64-v8a
2 | #
3 | #APP_ABI := all
4 | APP_PLATFORM := android-9
5 | APP_STL := c++_static
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/openh264-codec/README.md:
--------------------------------------------------------------------------------
1 | ## Notes
2 |
3 | Openh264 only support [YUV420 format](https://github.com/cisco/openh264/wiki#encoder-features).
4 |
5 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := arm64-v8a
2 | APP_PLATFORM := android-16
3 | APP_STL := c++_static
4 | #APP_STL := c++_shared
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := arm64-v8a
2 | APP_PLATFORM := android-16
3 | APP_STL := c++_static
4 | #APP_STL := c++_shared
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/fdkaac/lib/x86/libfdk-aac.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/fdkaac/lib/x86/libfdk-aac.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libx264/libs/x86/libx264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/libx264/libs/x86/libx264.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libx264/libs/x86_64/libx264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/libx264/libs/x86_64/libx264.a
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/fdkaac/lib/x86/libfdk-aac.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/openh264-codec/src/main/jni/fdkaac/lib/x86/libfdk-aac.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libx264/libs/arm64-v8a/libx264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/libx264/libs/arm64-v8a/libx264.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/fdkaac/lib/arm64-v8a/libfdk-aac.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/fdkaac/lib/arm64-v8a/libfdk-aac.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libopenh264/libs/x86/libopenh264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/libopenh264/libs/x86/libopenh264.a
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/fdkaac/lib/arm64-v8a/libfdk-aac.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/openh264-codec/src/main/jni/fdkaac/lib/arm64-v8a/libfdk-aac.a
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/libopenh264/libs/x86/libopenh264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/openh264-codec/src/main/jni/libopenh264/libs/x86/libopenh264.a
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libopenh264/libs/arm64-v8a/libopenh264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/x264-codec/src/main/jni/libopenh264/libs/arm64-v8a/libopenh264.a
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/libopenh264/libs/arm64-v8a/libopenh264.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BruceWind/SoftCodec/HEAD/openh264-codec/src/main/jni/libopenh264/libs/arm64-v8a/libopenh264.a
--------------------------------------------------------------------------------
/x264-codec/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libx264/include/x264_config.h:
--------------------------------------------------------------------------------
1 | #define X264_GPL 1
2 | #define X264_INTERLACED 1
3 | #define X264_BIT_DEPTH 0
4 | #define X264_CHROMA_FORMAT 0
5 | #define X264_VERSION ""
6 | #define X264_POINTVER "0.155.x"
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SoftCodec
3 | Cannt connect to %s
4 | connected to %s.
5 |
6 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/print_hex.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by bruce on 21-6-14.
3 | //
4 |
5 | #ifndef SOFTCODEC_PRINT_HEX_H
6 | #define SOFTCODEC_PRINT_HEX_H
7 |
8 | void print_hex(char * tag, unsigned char* data,int len);
9 | #endif //SOFTCODEC_PRINT_HEX_H
10 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on: [pull_request, push]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Checkout the code
8 | uses: actions/checkout@v2
9 | - name: Build the app
10 | run: ./gradlew build
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 20 23:04:35 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
7 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/librtmp.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=${prefix}
3 | libdir=@libdir@
4 | incdir=${prefix}/include
5 |
6 | Name: librtmp
7 | Description: RTMP implementation
8 | Version: @VERSION@
9 | Requires: @CRYPTO_REQ@
10 | URL: http://rtmpdump.mplayerhq.hu
11 | Libs: -L${libdir} -lrtmp -lz @PUBLIC_LIBS@
12 | Libs.private: @PRIVATE_LIBS@
13 | Cflags: -I${incdir}
14 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/librtmp.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=${prefix}
3 | libdir=@libdir@
4 | incdir=${prefix}/include
5 |
6 | Name: librtmp
7 | Description: RTMP implementation
8 | Version: @VERSION@
9 | Requires: @CRYPTO_REQ@
10 | URL: http://rtmpdump.mplayerhq.hu
11 | Libs: -L${libdir} -lrtmp -lz @PUBLIC_LIBS@
12 | Libs.private: @PRIVATE_LIBS@
13 | Cflags: -I${incdir}
14 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/rtmpManage.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include "xiecc_rtmp.h"
3 |
4 |
5 | /*
6 | *rtmp的连接
7 | */
8 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_open(JNIEnv *env,jobject instance, jstring url_);
9 |
10 |
11 | /*
12 | *断开rtmp的
13 | */
14 |
15 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_stop(JNIEnv *env,jobject instance);
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/rtmpManage.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 | /*
5 | *rtmp的连接
6 | */
7 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_open(JNIEnv *env,jobject instance, jstring url_);
8 |
9 | //TODO does it need to add pause function?
10 |
11 | /*
12 | *断开rtmp的
13 | */
14 |
15 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_stop(JNIEnv *env,jobject instance);
16 |
--------------------------------------------------------------------------------
/app/src/test/java/com/androidyuan/softcodec/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.androidyuan.softcodec;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/libopenh264/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 | LOCAL_MODULE := libopenh264
5 |
6 | ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
7 | LOCAL_SRC_FILES := libs/arm64-v8a/libopenh264.a
8 | endif
9 |
10 | ifeq ($(TARGET_ARCH_ABI),x86)
11 | LOCAL_SRC_FILES := libs/x86/libopenh264.a
12 | endif
13 |
14 | LOCAL_EXPORT_C_INCLUDES := include/wels
15 | include $(PREBUILT_STATIC_LIBRARY)
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/androidyuan/softcodec/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.androidyuan.softcodec;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/Android.mk:
--------------------------------------------------------------------------------
1 | ## depend librtmp with source code.
2 | LOCAL_PATH:= $(call my-dir)
3 |
4 | include $(CLEAR_VARS)
5 |
6 | LOCAL_MODULE := librtmp
7 |
8 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
9 |
10 | LOCAL_SRC_FILES := \
11 | amf.c \
12 | log.c \
13 | parseurl.c \
14 | rtmp.c \
15 | hashswf.c
16 |
17 | LOCAL_CFLAGS := -DRTMPDUMP_VERSION=v2.4 -DNO_CRYPTO
18 |
19 | include $(BUILD_STATIC_LIBRARY)
20 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/fdkaac/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 | include $(CLEAR_VARS)
3 |
4 | include $(CLEAR_VARS)
5 | LOCAL_MODULE :=static_aac
6 |
7 |
8 | ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
9 | LOCAL_SRC_FILES := lib/arm64-v8a/libfdk-aac.a
10 | endif
11 |
12 | ifeq ($(TARGET_ARCH_ABI),x86)
13 | LOCAL_SRC_FILES := lib/x86/libfdk-aac.a
14 | endif
15 |
16 |
17 | LOCAL_EXPORT_C_INCLUDES := include
18 | include $(PREBUILT_STATIC_LIBRARY)
19 |
20 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/Android.mk:
--------------------------------------------------------------------------------
1 | ## depend librtmp with source code.
2 | LOCAL_PATH:= $(call my-dir)
3 |
4 | include $(CLEAR_VARS)
5 |
6 | LOCAL_MODULE := librtmp
7 |
8 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
9 |
10 | LOCAL_SRC_FILES := \
11 | amf.c \
12 | log.c \
13 | parseurl.c \
14 | rtmp.c \
15 | hashswf.c
16 |
17 | LOCAL_CFLAGS := -DRTMPDUMP_VERSION=v2.4 -DNO_CRYPTO
18 |
19 | include $(BUILD_STATIC_LIBRARY)
20 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/print_hex.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "h264_encoder_log.h"
9 |
10 | void print_hex(char * tag, unsigned char* data,int len){
11 | char buffer[len*2+1];
12 | buffer[len*2]=0;
13 |
14 | for(auto j = 0; j < len; j++){
15 | sprintf(&buffer[2*j], "%02X", data[j]);
16 | }
17 | ALOGI("%s hex:%s",tag,buffer);
18 | }
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/Android.mk:
--------------------------------------------------------------------------------
1 | include $(call all-subdir-makefiles)
2 |
3 | LOCAL_PATH := $(call my-dir)
4 |
5 |
6 |
7 | include $(CLEAR_VARS)
8 | LOCAL_MODULE := share_x264
9 | LOCAL_SHARED_LIBRARIES := libx264
10 | LOCAL_STATIC_LIBRARIES := librtmp \
11 | static_aac
12 | LOCAL_LDLIBS := -ldl -lc -lz -lm -llog
13 | LOCAL_SRC_FILES := h264Encoder.c \
14 | xiecc_rtmp.c \
15 | aacEncode.c \
16 | rtmpManage.c
17 | include $(BUILD_SHARED_LIBRARY)
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/openh264-codec/src/test/java/io/github/brucewind/x264_codec/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.x264_codec;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 |
14 | @Test
15 | public void addition_isCorrect() {
16 | assertEquals(4, 2 + 2);
17 | }
18 | }
--------------------------------------------------------------------------------
/x264-codec/src/test/java/io/github/brucewind/x264_codec/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.x264_codec;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 |
14 | @Test
15 | public void addition_isCorrect() {
16 | assertEquals(4, 2 + 2);
17 | }
18 | }
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libopenh264/include/wels/codec_ver.h:
--------------------------------------------------------------------------------
1 | //The current file is auto-generated by script: generate_codec_ver.sh
2 | #ifndef CODEC_VER_H
3 | #define CODEC_VER_H
4 |
5 | #include "codec_app_def.h"
6 |
7 | static const OpenH264Version g_stCodecVersion = {2, 1, 1, 2005};
8 | static const char* const g_strCodecVer = "OpenH264 version:2.1.1.2005";
9 |
10 | #define OPENH264_MAJOR (2)
11 | #define OPENH264_MINOR (1)
12 | #define OPENH264_REVISION (1)
13 | #define OPENH264_RESERVED (2005)
14 |
15 | #endif // CODEC_VER_H
16 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/libopenh264/include/wels/codec_ver.h:
--------------------------------------------------------------------------------
1 | //The current file is auto-generated by script: generate_codec_ver.sh
2 | #ifndef CODEC_VER_H
3 | #define CODEC_VER_H
4 |
5 | #include "codec_app_def.h"
6 |
7 | static const OpenH264Version g_stCodecVersion = {2, 1, 1, 2005};
8 | static const char* const g_strCodecVer = "OpenH264 version:2.1.1.2005";
9 |
10 | #define OPENH264_MAJOR (2)
11 | #define OPENH264_MINOR (1)
12 | #define OPENH264_REVISION (1)
13 | #define OPENH264_RESERVED (2005)
14 |
15 | #endif // CODEC_VER_H
16 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/Android.mk:
--------------------------------------------------------------------------------
1 | include $(call all-subdir-makefiles)
2 |
3 | LOCAL_PATH := $(call my-dir)
4 |
5 |
6 |
7 | include $(CLEAR_VARS)
8 |
9 | LOCAL_CPPFLAGS += -O3 -std=c++11
10 | LOCAL_MODULE := softcodec
11 | LOCAL_SHARED_LIBRARIES := libopenh264 \
12 | librtmp \
13 | static_aac
14 | LOCAL_LDLIBS := -ldl -lc -lz -lm -llog
15 | LOCAL_SRC_FILES := h264Encoder.cc \
16 | xiecc_rtmp.c \
17 | aacEncode.c \
18 | rtmpManage.c
19 |
20 | include $(BUILD_SHARED_LIBRARY)
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/fdkaac/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 | include $(CLEAR_VARS)
3 |
4 | include $(CLEAR_VARS)
5 | LOCAL_MODULE :=static_aac
6 | ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
7 | LOCAL_SRC_FILES := lib/armeabi-v7a/libfdk-aac.a
8 | endif
9 |
10 | ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
11 | LOCAL_SRC_FILES := lib/arm64-v8a/libfdk-aac.a
12 | endif
13 |
14 | ifeq ($(TARGET_ARCH_ABI),x86)
15 | LOCAL_SRC_FILES := lib/x86/libfdk-aac.a
16 | endif
17 |
18 |
19 | LOCAL_EXPORT_C_INCLUDES := include
20 | include $(PREBUILT_STATIC_LIBRARY)
21 |
22 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/stdint.h:
--------------------------------------------------------------------------------
1 | #ifndef CODEC_STDINT_H
2 | #define CODEC_STDINT_H
3 |
4 | #ifndef _MSC_VER
5 |
6 | #include
7 |
8 | #else
9 |
10 | typedef signed char int8_t ;
11 | typedef unsigned char uint8_t ;
12 | typedef short int16_t ;
13 | typedef unsigned short uint16_t;
14 | typedef int int32_t ;
15 | typedef unsigned int uint32_t;
16 | typedef __int64 int64_t ;
17 | typedef unsigned __int64 uint64_t;
18 | typedef short int_least16_t;
19 |
20 | #endif
21 |
22 | #endif //CODEC_STDINT_H
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libx264/Android.mk:
--------------------------------------------------------------------------------
1 |
2 | LOCAL_PATH := $(call my-dir)
3 |
4 | include $(CLEAR_VARS)
5 | LOCAL_MODULE := libx264
6 |
7 | ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
8 | LOCAL_SRC_FILES := libs/armeabi-v7a/libx264.a
9 | endif
10 |
11 | ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
12 | LOCAL_SRC_FILES := libs/arm64-v8a/libx264.a
13 | endif
14 |
15 | ifeq ($(TARGET_ARCH_ABI),x86)
16 | LOCAL_SRC_FILES := libs/x86/libx264.a
17 | endif
18 |
19 | ifeq ($(TARGET_ARCH_ABI),mips)
20 | LOCAL_SRC_FILES := libs/mips/libx264.a
21 | endif
22 |
23 | LOCAL_EXPORT_C_INCLUDES := include
24 | include $(PREBUILT_STATIC_LIBRARY)
25 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/rtmpManage.c:
--------------------------------------------------------------------------------
1 | #include "rtmpManage.h"
2 |
3 |
4 | /*
5 | *rtmp的连接
6 | */
7 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_rtmpOpen(JNIEnv *env,
8 | jobject instance, jstring url_) {
9 |
10 | const char *url = (*env)->GetStringUTFChars(env, url_, 0);
11 |
12 | int result = rtmp_open_for_write(url);
13 |
14 | (*env)->ReleaseStringUTFChars(env, url_, url);
15 |
16 | return result;
17 | }
18 |
19 | /*
20 | *断开rtmp的连接
21 | */
22 |
23 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_rtmpStop(JNIEnv *env,
24 | jobject instance) {
25 |
26 | int result = stopRtmpConnect();
27 |
28 | return result;
29 | }
30 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/rtmpManage.c:
--------------------------------------------------------------------------------
1 | #include "rtmpManage.h"
2 | #include "xiecc_rtmp.h"
3 |
4 |
5 | /*
6 | *rtmp的连接
7 | */
8 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_rtmpOpen(JNIEnv *env,
9 | jobject instance, jstring url_) {
10 |
11 | const char *url = (*env)->GetStringUTFChars(env, url_, 0);
12 |
13 | int result = rtmp_open_for_write(url);
14 |
15 | (*env)->ReleaseStringUTFChars(env, url_, url);
16 |
17 | return result;
18 | }
19 |
20 | /*
21 | *断开rtmp的连接
22 | */
23 |
24 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_rtmpStop(JNIEnv *env,
25 | jobject instance) {
26 |
27 | int result = stopRtmpConnect();
28 |
29 | return result;
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/wei/文档/tools/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/h264_encoder_log.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by bruce on 5/1/21.
3 | //
4 |
5 | #ifndef SOFTCODEC_H264_ENCODER_LOG_H
6 | #define SOFTCODEC_H264_ENCODER_LOG_H
7 |
8 |
9 | #define LOGTAG "LiveCamera_encoder"
10 | #define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOGTAG, __VA_ARGS__)
11 | #define printf(...) LOGI(__VA_ARGS__)
12 | #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOGTAG, __VA_ARGS__)
13 | #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG , LOGTAG, __VA_ARGS__)
14 | #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO , LOGTAG, __VA_ARGS__)
15 | #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN , LOGTAG, __VA_ARGS__)
16 | #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR , LOGTAG, __VA_ARGS__)
17 |
18 |
19 |
20 | #endif //SOFTCODEC_H264_ENCODER_LOG_H
21 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/h264_encoder_log.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by bruce on 5/1/21.
3 | //
4 |
5 | #ifndef SOFTCODEC_H264_ENCODER_LOG_H
6 | #define SOFTCODEC_H264_ENCODER_LOG_H
7 |
8 |
9 | #define LOGTAG "LiveCamera_encoder"
10 | #define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOGTAG, __VA_ARGS__)
11 | #define printf(...) LOGI(__VA_ARGS__)
12 | #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOGTAG, __VA_ARGS__)
13 | #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG , LOGTAG, __VA_ARGS__)
14 | #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO , LOGTAG, __VA_ARGS__)
15 | #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN , LOGTAG, __VA_ARGS__)
16 | #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR , LOGTAG, __VA_ARGS__)
17 |
18 |
19 |
20 | #endif //SOFTCODEC_H264_ENCODER_LOG_H
21 |
--------------------------------------------------------------------------------
/x264-codec/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/openh264-codec/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
10 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/x264-codec/src/main/java/io/github/brucewind/softcodec/StreamHelper.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | /**
4 | * Created by bruce on 16-11-24.
5 | * It is used to connect server and push stream.
6 | */
7 | class StreamHelper {
8 |
9 |
10 | static {
11 | System.loadLibrary("share_x264");
12 | }
13 |
14 | /**
15 | * connect rtmp server
16 | */
17 | public native int rtmpOpen(String url);
18 |
19 | public native int rtmpStop();
20 |
21 | /**
22 | * x264 function
23 | * @param encoder
24 | * @param NV12
25 | * @param NV12size
26 | * @param H264
27 | * @return
28 | */
29 | public native int compressBuffer(long encoder, byte[] NV12, int NV12size, byte[] H264);
30 |
31 | public native long compressBegin(int width, int height, int bitrate, int fps);
32 |
33 | public native int compressEnd(long encoder);
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/h264Encoder.h:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "xiecc_rtmp.h"
8 | #include "../libopenh264/include/wels/codec_app_def.h"
9 | #include "../libopenh264/include/wels/codec_api.h"
10 | #include "h264_encoder_log.h"
11 |
12 |
13 | extern "C" JNIEXPORT jlong
14 | Java_io_github_brucewind_softcodec_StreamHelper_compressBegin(JNIEnv * env ,
15 | jobject thiz, jint
16 | width , jint height, jint
17 | bitrate , jint fps);
18 |
19 | extern "C" JNIEXPORT jint
20 | Java_io_github_brucewind_softcodec_StreamHelper_compressEnd(JNIEnv * env ,
21 | jobject thiz, jlong
22 | handle );
23 |
24 | extern "C" JNIEXPORT jint
25 | Java_io_github_brucewind_softcodec_StreamHelper_compressBuffer(JNIEnv * env ,
26 | jobject thiz,
27 | jlong
28 | handle ,
29 | jbyteArray in,
30 | jint
31 | insize ,
32 | jbyteArray out );
--------------------------------------------------------------------------------
/openh264-codec/src/main/java/io/github/brucewind/softcodec/StreamHelper.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | /**
4 | * Created by bruce on 16-11-24.
5 | * It is used to connect server and push stream.
6 | */
7 | class StreamHelper {
8 |
9 |
10 | static {
11 | System.loadLibrary("softcodec");
12 | }
13 |
14 | /**
15 | * connect rtmp server
16 | */
17 | public native int rtmpOpen(String url);
18 |
19 | public native int rtmpStop();
20 |
21 | /**
22 | * x264 function
23 | * @param encoder
24 | * @param I420
25 | * @param I420Size
26 | * @param H264, it is unused.
27 | * @return
28 | */
29 | public native int compressBuffer(long encoder, byte[] I420, int I420Size, byte[] H264);
30 |
31 | public native long compressBegin(int width, int height, int bitrate, int fps);
32 |
33 | public native int compressEnd(long encoder);
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/xiecc_rtmp.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by faraklit on 08.02.2016.
3 | //
4 |
5 | #ifndef _XIECC_RTMP_H_
6 | #define _XIECC_RTMP_H_
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #ifdef __cplusplus
13 | extern "C"{
14 | #endif
15 |
16 |
17 | static int getSystemTime() {
18 | struct timeval tv; //获取一个时间结构
19 | gettimeofday(&tv, NULL); //获取当前时间
20 | int t = tv.tv_sec;
21 | t *= 1000;
22 | t += tv.tv_usec / 1000;
23 | return t;
24 | }
25 |
26 | int rtmp_open_for_write(const char * url);
27 |
28 | void send_video_sps_pps(uint8_t *sps,int sps_len,uint8_t *pps,int pps_len);
29 |
30 | void send_rtmp_video(uint8_t *data, int data_len,int timestamp) ;
31 |
32 | void send_rtmp_audio_spec(unsigned char *spec_buf, uint32_t spec_len);
33 |
34 | void send_rtmp_audio(unsigned char *buf, uint32_t len,int time) ;
35 | #ifdef __cplusplus
36 | }
37 | #endif
38 | #endif
39 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/h264Encoder.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include <../libx264/include/x264.h>
7 | #include "xiecc_rtmp.h"
8 |
9 | /*compressBegin
10 | *初始化x264
11 | *width 宽度
12 | *height 高度
13 | *bitrate 码率
14 | *fps 幀率
15 | */
16 | JNIEXPORT jlong Java_io_github_brucewind_softcodec_StreamHelper_compressBegin(JNIEnv* env,
17 | jobject thiz, jint width, jint height, jint bitrate, jint fps);
18 |
19 | /*compressEnd
20 | *結束x264编码
21 | *handle
22 | */
23 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_compressEnd(JNIEnv* env,
24 | jobject thiz, jlong handle);
25 |
26 | /*compressBegin
27 | *编码x264
28 | *handle
29 | *in nv12
30 | *insize nv12 长度
31 | *out h264
32 | */
33 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_compressBuffer(JNIEnv* env,
34 | jobject thiz,
35 | jlong handle,
36 | jbyteArray in,
37 | jint insize,
38 | jbyteArray out);
39 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/xiecc_rtmp.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by faraklit on 08.02.2016.
3 | //
4 |
5 | #ifndef _XIECC_RTMP_H_
6 | #define _XIECC_RTMP_H_
7 | #include "../libopenh264/include/wels/codec_def.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #ifdef __cplusplus
15 | extern "C"{
16 | #endif
17 |
18 |
19 | static int getSystemTime() {
20 | struct timeval tv; //获取一个时间结构
21 | gettimeofday(&tv, NULL); //获取当前时间
22 | int t = tv.tv_sec;
23 | t *= 1000;
24 | t += tv.tv_usec / 1000;
25 | return t;
26 | }
27 |
28 | int isConnected();
29 |
30 | int rtmp_open_for_write(const char * url);
31 |
32 | void send_video_sps_pps(uint8_t *sps,int sps_len,uint8_t *pps,int pps_len);
33 |
34 | void send_rtmp_video(uint8_t *data, uint32_t data_len,int timestamp) ;
35 |
36 | void send_rtmp_audio_spec(unsigned char *spec_buf, uint32_t spec_len);
37 |
38 | void send_rtmp_audio(unsigned char *buf, uint32_t len,int time) ;
39 | #ifdef __cplusplus
40 | }
41 | #endif
42 | #endif
43 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/aacEncode.h:
--------------------------------------------------------------------------------
1 | #include "../fdkaac/include/aacenc_lib.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "xiecc_rtmp.h"
8 | #include "stdbool.h"
9 |
10 |
11 |
12 | typedef struct AudioOutput {
13 | int transMux; //TODO ??
14 | int afterburner; //TODO ??
15 | int channelLoader; //TODO ??
16 | int aot ; //aot类型。
17 | int channels;
18 | int samplerate;
19 | int bitrate;
20 | CHANNEL_MODE mode; //通道模式。
21 | HANDLE_AACENCODER handle; //aac处理实例
22 | AACENC_InfoStruct info;
23 | int input_size;
24 | int first;
25 | }AACOutput;
26 |
27 | typedef struct EncodeAAC Encode;
28 | jint Java_io_github_brucewind_softcodec_AudioRecorder_initAAC(JNIEnv* env,jobject thiz, jint bitrate,jint samplerate,jint channels);
29 | jint Java_io_github_brucewind_softcodec_AudioRecorder_getbuffersize(JNIEnv* env, jobject thiz);
30 | jboolean Java_io_github_brucewind_softcodec_AudioRecorder_encodeFrame(JNIEnv *pEnv,jobject obj,jbyteArray pcmData);
31 | bool aacEncoderProcess(AACENC_BufDesc* in_buf,AACENC_BufDesc* out_buf,AACENC_InArgs* in_args,AACENC_OutArgs* out_args);
32 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/aacEncode.h:
--------------------------------------------------------------------------------
1 | #include "../fdkaac/include/aacenc_lib.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "xiecc_rtmp.h"
8 | #include "stdbool.h"
9 |
10 |
11 |
12 | typedef struct AudioOutput {
13 | int transMux; //TODO ??
14 | int afterburner; //TODO ??
15 | int channelLoader; //TODO ??
16 | int aot ; //aot类型。
17 | int channels;
18 | int samplerate;
19 | int bitrate;
20 | CHANNEL_MODE mode; //通道模式。
21 | HANDLE_AACENCODER handle; //aac处理实例
22 | AACENC_InfoStruct info;
23 | int input_size;
24 | int first;
25 | }AACOutput;
26 |
27 | typedef struct EncodeAAC Encode;
28 | jint Java_io_github_brucewind_softcodec_AudioRecorder_initAAC(JNIEnv* env,jobject thiz, jint bitrate,jint samplerate,jint channels);
29 | jint Java_io_github_brucewind_softcodec_AudioRecorder_getbuffersize(JNIEnv* env, jobject thiz);
30 | jboolean Java_io_github_brucewind_softcodec_AudioRecorder_encodeFrame(JNIEnv *pEnv,jobject obj,jbyteArray pcmData);
31 | bool aacEncoderProcess(AACENC_BufDesc* in_buf,AACENC_BufDesc* out_buf,AACENC_InArgs* in_args,AACENC_OutArgs* out_args);
32 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/x264-codec/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdkVersion 24
7 | buildToolsVersion "24.0.3"
8 |
9 | ndkVersion "16.1.4479499"
10 |
11 | defaultConfig {
12 | minSdkVersion 21
13 | targetSdkVersion 21
14 | versionCode 1
15 | versionName "1.0"
16 | ndk {
17 | // Specifies the ABI configurations of your native
18 | // libraries Gradle should build and package with your APK.
19 | abiFilters 'arm64-v8a'
20 | }
21 | }
22 |
23 | buildTypes {
24 | release {
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 |
30 | externalNativeBuild {
31 | ndkBuild {
32 | path file('src/main/jni/Android.mk')
33 | }
34 | }
35 | compileOptions {
36 | sourceCompatibility JavaVersion.VERSION_1_7
37 | targetCompatibility JavaVersion.VERSION_1_7
38 | }
39 |
40 | lintOptions {
41 | abortOnError false
42 | }
43 | }
44 |
45 | dependencies {
46 | testImplementation 'junit:junit:4.+'
47 | }
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.3"
6 |
7 | //If I don't write this line, C codes will build with latest version of NDK.
8 | // ndkVersion "16.1.4479499"
9 | ndkVersion "21.4.7075529"
10 |
11 | defaultConfig {
12 | applicationId "com.androidyuan.softcodec"
13 | minSdkVersion 21
14 | targetSdkVersion 21
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | //In the event that I have not written this line, so file won't packaged into apk.
19 | ndk {
20 | abiFilters 'arm64-v8a','x86' //setting only one abi make apk smaller.
21 | }
22 | }
23 |
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
28 | }
29 | }
30 |
31 |
32 | lintOptions {
33 | abortOnError false
34 | }
35 | }
36 |
37 |
38 | dependencies {
39 | testImplementation 'junit:junit:4.12'
40 | implementation 'com.android.support:appcompat-v7:24.0.0'
41 | // implementation "com.android.support.constraint:constraint-layout:2.0.4"
42 | implementation project(':openh264-codec')
43 | }
44 |
--------------------------------------------------------------------------------
/openh264-codec/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdkVersion 24
7 | buildToolsVersion "24.0.3"
8 |
9 | ndkVersion '21.1.6352462'
10 | // ndkVersion "16.1.4479499"
11 |
12 | defaultConfig {
13 | minSdkVersion 21
14 | targetSdkVersion 21
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | externalNativeBuild {
19 | cmake {
20 | cppFlags "-std=c++11"
21 | abiFilters 'arm64-v8a', 'x86'// ,'armeabi-v7a',
22 | }
23 |
24 | // ndk {
25 | // abiFilters 'arm64-v8a'
26 | // }
27 | }
28 | }
29 |
30 | buildTypes {
31 | release {
32 | minifyEnabled false
33 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
34 | }
35 | }
36 | externalNativeBuild {
37 | cmake {
38 | path "src/main/jni/CMakeLists.txt"
39 | version "3.10.2"
40 | }
41 | // ndkBuild {
42 | // path file('src/main/jni/Android.mk')
43 | // }
44 | }
45 | compileOptions {
46 | sourceCompatibility JavaVersion.VERSION_1_7
47 | targetCompatibility JavaVersion.VERSION_1_7
48 | }
49 |
50 | lintOptions {
51 | abortOnError false
52 | }
53 | }
54 |
55 | dependencies {
56 | testImplementation 'junit:junit:4.+'
57 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
19 |
20 |
28 |
29 |
37 |
38 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/http.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_HTTP_H__
2 | #define __RTMP_HTTP_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | * Copyright (C) 2010 Antti Ajanki
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | typedef enum {
27 | HTTPRES_OK, /* result OK */
28 | HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */
29 | HTTPRES_NOT_FOUND, /* not found */
30 | HTTPRES_BAD_REQUEST, /* client error */
31 | HTTPRES_SERVER_ERROR, /* server reported an error */
32 | HTTPRES_REDIRECTED, /* resource has been moved */
33 | HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */
34 | } HTTPResult;
35 |
36 | struct HTTP_ctx {
37 | char *date;
38 | int size;
39 | int status;
40 | void *data;
41 | };
42 |
43 | typedef size_t (HTTP_read_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
44 |
45 | HTTPResult HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb);
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/http.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_HTTP_H__
2 | #define __RTMP_HTTP_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | * Copyright (C) 2010 Antti Ajanki
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | typedef enum {
27 | HTTPRES_OK, /* result OK */
28 | HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */
29 | HTTPRES_NOT_FOUND, /* not found */
30 | HTTPRES_BAD_REQUEST, /* client error */
31 | HTTPRES_SERVER_ERROR, /* server reported an error */
32 | HTTPRES_REDIRECTED, /* resource has been moved */
33 | HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */
34 | } HTTPResult;
35 |
36 | struct HTTP_ctx {
37 | char *date;
38 | int size;
39 | int status;
40 | void *data;
41 | };
42 |
43 | typedef size_t (HTTP_read_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
44 |
45 | HTTPResult HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb);
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/java/io/github/brucewind/softcodec/YUVHelper.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | /**
6 | * It is used to convert YUV format of data to another format.
7 | */
8 | public final class YUVHelper {
9 | /**
10 | * I420 to nv21
11 | */
12 | public static byte[] I420ToNV21(byte[] data, int width, int height) {
13 | byte[] ret = new byte[data.length];
14 | int total = width * height;
15 |
16 | ByteBuffer bufferY = ByteBuffer.wrap(ret, 0, total);
17 | ByteBuffer bufferVU = ByteBuffer.wrap(ret, total, total / 2);
18 |
19 | bufferY.put(data, 0, total);
20 | for (int i = 0; i < total / 4; i += 1) {
21 | bufferVU.put(data[i + total + total / 4]);
22 | bufferVU.put(data[total + i]);
23 | }
24 |
25 | return ret;
26 | }
27 |
28 |
29 | /**
30 | * nv21 to I420
31 | * @param data
32 | * @param width
33 | * @param height
34 | * @return
35 | */
36 | public static byte[] nv21ToI420(byte[] data, int width, int height) {
37 | byte[] ret = new byte[data.length];
38 | int total = width * height;
39 |
40 | ByteBuffer bufferY = ByteBuffer.wrap(ret, 0, total);
41 | ByteBuffer bufferU = ByteBuffer.wrap(ret, total, total / 4);
42 | ByteBuffer bufferV = ByteBuffer.wrap(ret, total + total / 4, total / 4);
43 |
44 | bufferY.put(data, 0, total);
45 | for (int i=total; i
28 | #include
29 | #include
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 | /* Enable this to get full debugging output */
35 | /* #define _DEBUG */
36 |
37 | #ifdef _DEBUG
38 | #undef NODEBUG
39 | #endif
40 |
41 | typedef enum
42 | { RTMP_LOGCRIT=0, RTMP_LOGERROR, RTMP_LOGWARNING, RTMP_LOGINFO,
43 | RTMP_LOGDEBUG, RTMP_LOGDEBUG2, RTMP_LOGALL
44 | } RTMP_LogLevel;
45 |
46 | extern RTMP_LogLevel RTMP_debuglevel;
47 |
48 | typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list);
49 | void RTMP_LogSetCallback(RTMP_LogCallback *cb);
50 | void RTMP_LogSetOutput(FILE *file);
51 | #ifdef __GNUC__
52 | void RTMP_LogPrintf(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
53 | void RTMP_LogStatus(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
54 | void RTMP_Log(int level, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
55 | #else
56 | void RTMP_LogPrintf(const char *format, ...);
57 | void RTMP_LogStatus(const char *format, ...);
58 | void RTMP_Log(int level, const char *format, ...);
59 | #endif
60 | void RTMP_LogHex(int level, const uint8_t *data, unsigned long len);
61 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len);
62 | void RTMP_LogSetLevel(RTMP_LogLevel lvl);
63 | RTMP_LogLevel RTMP_LogGetLevel(void);
64 |
65 | #ifdef __cplusplus
66 | }
67 | #endif
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/log.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008-2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #ifndef __RTMP_LOG_H__
25 | #define __RTMP_LOG_H__
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 | /* Enable this to get full debugging output */
35 | /* #define _DEBUG */
36 |
37 | #ifdef _DEBUG
38 | #undef NODEBUG
39 | #endif
40 |
41 | typedef enum
42 | { RTMP_LOGCRIT=0, RTMP_LOGERROR, RTMP_LOGWARNING, RTMP_LOGINFO,
43 | RTMP_LOGDEBUG, RTMP_LOGDEBUG2, RTMP_LOGALL
44 | } RTMP_LogLevel;
45 |
46 | extern RTMP_LogLevel RTMP_debuglevel;
47 |
48 | typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list);
49 | void RTMP_LogSetCallback(RTMP_LogCallback *cb);
50 | void RTMP_LogSetOutput(FILE *file);
51 | #ifdef __GNUC__
52 | void RTMP_LogPrintf(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
53 | void RTMP_LogStatus(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
54 | void RTMP_Log(int level, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
55 | #else
56 | void RTMP_LogPrintf(const char *format, ...);
57 | void RTMP_LogStatus(const char *format, ...);
58 | void RTMP_Log(int level, const char *format, ...);
59 | #endif
60 | void RTMP_LogHex(int level, const uint8_t *data, unsigned long len);
61 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len);
62 | void RTMP_LogSetLevel(RTMP_LogLevel lvl);
63 | RTMP_LogLevel RTMP_LogGetLevel(void);
64 |
65 | #ifdef __cplusplus
66 | }
67 | #endif
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/x264-codec/src/main/java/io/github/brucewind/softcodec/RtmpHelper.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | import java.util.Timer;
4 | import java.util.TimerTask;
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import android.util.Log;
8 | import java.util.concurrent.TimeUnit;
9 | import java.util.concurrent.atomic.AtomicInteger;
10 |
11 | /**
12 | * Created by bruce on 16-11-27.
13 | *
14 | * It is used to manager picture to be encode, and transfer encoded data to server in {@link ExecutorService}.
15 | */
16 | public class RtmpHelper {
17 |
18 | private ExecutorService mRtmpExecutor = Executors.newSingleThreadExecutor();
19 | private Timer mTimer;
20 | private final AtomicInteger mFpsAtomic = new AtomicInteger(0);
21 | private final StreamHelper mStreamHelper = new StreamHelper();
22 |
23 | /*rtmp*/
24 | public int rtmpOpen(final String url) {
25 | mTimer = new Timer();
26 | mTimer.schedule(new TimerTask() {
27 | @Override
28 | public void run() {
29 | Log.d("RtmpHelper", "fps = " + mFpsAtomic.get());
30 | mFpsAtomic.set(0);
31 | }
32 | }, 1000, 1000);
33 |
34 | return mStreamHelper.rtmpOpen(url);
35 | }
36 |
37 | public int rtmpStop() {
38 | if (mTimer != null) {
39 | mTimer.cancel();
40 | }
41 |
42 | mRtmpExecutor.execute(new Runnable() {
43 | @Override
44 | public void run() {
45 | mStreamHelper.rtmpStop();
46 | mRtmpExecutor.shutdown();
47 | try {
48 | final ExecutorService temp = mRtmpExecutor;
49 | temp.awaitTermination(1, TimeUnit.SECONDS);
50 | } catch (InterruptedException e) {
51 | e.printStackTrace();
52 | }
53 |
54 | mRtmpExecutor = Executors.newSingleThreadExecutor();
55 |
56 | }
57 | });
58 | return 0;
59 | }
60 |
61 | /*x264 funtion*/
62 | public int compressBuffer(final long encoder, final byte[] NV12, final int NV12size,
63 | final byte[] H264) {
64 | mRtmpExecutor.execute(new Runnable() {
65 | @Override
66 | public void run() {
67 | mStreamHelper.compressBuffer(encoder, NV12, NV12size, H264);
68 | mFpsAtomic.incrementAndGet();
69 | }
70 | });
71 | return 0;
72 | }
73 |
74 | public long compressBegin(final int width, int height, int bitrate, int fps) {
75 | return mStreamHelper.compressBegin(width, height, bitrate, fps);
76 | }
77 |
78 | public int compressEnd(long encoder) {
79 | return mStreamHelper.compressEnd(encoder);
80 | }
81 |
82 | public void startRecordeAudio(int currenttime) {
83 | AudioRecorder.startRecorde(currenttime);
84 | }
85 |
86 | public void stopRecordeAudio() {
87 | AudioRecorder.stopRecorde();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/java/io/github/brucewind/softcodec/RtmpHelper.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | import java.util.Timer;
4 | import java.util.TimerTask;
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import android.util.Log;
8 | import java.util.concurrent.TimeUnit;
9 | import java.util.concurrent.atomic.AtomicInteger;
10 |
11 | /**
12 | * Created by bruce on 16-11-27.
13 | *
14 | * It is used to manager picture to be encode, and transfer encoded data to server in {@link ExecutorService}.
15 | */
16 | public class RtmpHelper {
17 |
18 | private static String LOGTAG="JLiveCamera_encoder";
19 |
20 | private ExecutorService mRtmpExecutor = Executors.newSingleThreadExecutor();
21 | private Timer mTimer;
22 | private final AtomicInteger mFpsAtomic = new AtomicInteger(0);
23 | private final StreamHelper mStreamHelper = new StreamHelper();
24 |
25 | /*rtmp*/
26 | public int rtmpOpen(final String url) {
27 | mTimer = new Timer();
28 | mTimer.schedule(new TimerTask() {
29 | @Override
30 | public void run() {
31 | Log.d(LOGTAG, "fps = " + mFpsAtomic.get());
32 | mFpsAtomic.set(0);
33 | }
34 | }, 1000, 1000);
35 |
36 | return mStreamHelper.rtmpOpen(url);
37 | }
38 |
39 | public int rtmpStop() {
40 | if (mTimer != null) {
41 | mTimer.cancel();
42 | }
43 |
44 | mRtmpExecutor.execute(new Runnable() {
45 | @Override
46 | public void run() {
47 | mStreamHelper.rtmpStop();
48 | mRtmpExecutor.shutdown();
49 | try {
50 | final ExecutorService temp = mRtmpExecutor;
51 | temp.awaitTermination(1, TimeUnit.SECONDS);
52 | } catch (InterruptedException e) {
53 | e.printStackTrace();
54 | }
55 |
56 | mRtmpExecutor = Executors.newSingleThreadExecutor();
57 |
58 | }
59 | });
60 | return 0;
61 | }
62 |
63 | /*x264 funtion*/
64 | public int compressBuffer(final long encoder, final byte[] NV12, final int NV12size,
65 | final byte[] H264) {
66 | mRtmpExecutor.execute(new Runnable() {
67 | @Override
68 | public void run() {
69 |
70 | Log.d(LOGTAG, "compressBuffer("+NV12size+")");
71 | mStreamHelper.compressBuffer(encoder, NV12, NV12size, H264);
72 | mFpsAtomic.incrementAndGet();
73 | }
74 | });
75 | return 0;
76 | }
77 |
78 | public long compressBegin(final int width, int height, int bitrate, int fps) {
79 | return mStreamHelper.compressBegin(width, height, bitrate, fps);
80 | }
81 |
82 | public int compressEnd(long encoder) {
83 | return mStreamHelper.compressEnd(encoder);
84 | }
85 |
86 | public void startRecordeAudio(int currenttime) {
87 | AudioRecorder.startRecorde(currenttime);
88 | }
89 |
90 | public void stopRecordeAudio() {
91 | AudioRecorder.stopRecorde();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/bytes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2005-2008 Team XBMC
3 | * http://www.xbmc.org
4 | * Copyright (C) 2008-2009 Andrej Stepanchuk
5 | * Copyright (C) 2009-2010 Howard Chu
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | #ifndef __BYTES_H__
27 | #define __BYTES_H__
28 |
29 | #include
30 |
31 | #ifdef _WIN32
32 | /* Windows is little endian only */
33 | #define __LITTLE_ENDIAN 1234
34 | #define __BIG_ENDIAN 4321
35 | #define __BYTE_ORDER __LITTLE_ENDIAN
36 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
37 |
38 | typedef unsigned char uint8_t;
39 |
40 | #else /* !_WIN32 */
41 |
42 | #include
43 |
44 | #if defined(BYTE_ORDER) && !defined(__BYTE_ORDER)
45 | #define __BYTE_ORDER BYTE_ORDER
46 | #endif
47 |
48 | #if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN)
49 | #define __BIG_ENDIAN BIG_ENDIAN
50 | #endif
51 |
52 | #if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
53 | #define __LITTLE_ENDIAN LITTLE_ENDIAN
54 | #endif
55 |
56 | #endif /* !_WIN32 */
57 |
58 | /* define default endianness */
59 | #ifndef __LITTLE_ENDIAN
60 | #define __LITTLE_ENDIAN 1234
61 | #endif
62 |
63 | #ifndef __BIG_ENDIAN
64 | #define __BIG_ENDIAN 4321
65 | #endif
66 |
67 | #ifndef __BYTE_ORDER
68 | #warning "Byte order not defined on your system, assuming little endian!"
69 | #define __BYTE_ORDER __LITTLE_ENDIAN
70 | #endif
71 |
72 | /* ok, we assume to have the same float word order and byte order if float word order is not defined */
73 | #ifndef __FLOAT_WORD_ORDER
74 | #warning "Float word order not defined, assuming the same as byte order!"
75 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
76 | #endif
77 |
78 | #if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER)
79 | #error "Undefined byte or float word order!"
80 | #endif
81 |
82 | #if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN
83 | #error "Unknown/unsupported float word order!"
84 | #endif
85 |
86 | #if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN
87 | #error "Unknown/unsupported byte order!"
88 | #endif
89 |
90 | #endif
91 |
92 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/bytes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2005-2008 Team XBMC
3 | * http://www.xbmc.org
4 | * Copyright (C) 2008-2009 Andrej Stepanchuk
5 | * Copyright (C) 2009-2010 Howard Chu
6 | *
7 | * This file is part of librtmp.
8 | *
9 | * librtmp is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU Lesser General Public License as
11 | * published by the Free Software Foundation; either version 2.1,
12 | * or (at your option) any later version.
13 | *
14 | * librtmp is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public License
20 | * along with librtmp see the file COPYING. If not, write to
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 | * Boston, MA 02110-1301, USA.
23 | * http://www.gnu.org/copyleft/lgpl.html
24 | */
25 |
26 | #ifndef __BYTES_H__
27 | #define __BYTES_H__
28 |
29 | #include
30 |
31 | #ifdef _WIN32
32 | /* Windows is little endian only */
33 | #define __LITTLE_ENDIAN 1234
34 | #define __BIG_ENDIAN 4321
35 | #define __BYTE_ORDER __LITTLE_ENDIAN
36 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
37 |
38 | typedef unsigned char uint8_t;
39 |
40 | #else /* !_WIN32 */
41 |
42 | #include
43 |
44 | #if defined(BYTE_ORDER) && !defined(__BYTE_ORDER)
45 | #define __BYTE_ORDER BYTE_ORDER
46 | #endif
47 |
48 | #if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN)
49 | #define __BIG_ENDIAN BIG_ENDIAN
50 | #endif
51 |
52 | #if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
53 | #define __LITTLE_ENDIAN LITTLE_ENDIAN
54 | #endif
55 |
56 | #endif /* !_WIN32 */
57 |
58 | /* define default endianness */
59 | #ifndef __LITTLE_ENDIAN
60 | #define __LITTLE_ENDIAN 1234
61 | #endif
62 |
63 | #ifndef __BIG_ENDIAN
64 | #define __BIG_ENDIAN 4321
65 | #endif
66 |
67 | #ifndef __BYTE_ORDER
68 | #warning "Byte order not defined on your system, assuming little endian!"
69 | #define __BYTE_ORDER __LITTLE_ENDIAN
70 | #endif
71 |
72 | /* ok, we assume to have the same float word order and byte order if float word order is not defined */
73 | #ifndef __FLOAT_WORD_ORDER
74 | #warning "Float word order not defined, assuming the same as byte order!"
75 | #define __FLOAT_WORD_ORDER __BYTE_ORDER
76 | #endif
77 |
78 | #if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER)
79 | #error "Undefined byte or float word order!"
80 | #endif
81 |
82 | #if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN
83 | #error "Unknown/unsupported float word order!"
84 | #endif
85 |
86 | #if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN
87 | #error "Unknown/unsupported byte order!"
88 | #endif
89 |
90 | #endif
91 |
92 |
--------------------------------------------------------------------------------
/x264-codec/src/main/java/io/github/brucewind/softcodec/AudioRecorder.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioRecord;
5 | import android.media.MediaRecorder;
6 | import android.media.MediaRecorder.AudioSource;
7 | import android.util.Log;
8 |
9 | /**
10 | * Obviously it is used to record audio.
11 | */
12 | public class AudioRecorder {
13 |
14 | static final String TAG = "AudioRecorder";
15 |
16 | private static AudioRecord mAudioRecord = null;
17 | private static boolean isRecording = false;// 录音标志位
18 | private static final int frequency = 44100;
19 | private static final int channel = AudioFormat.CHANNEL_IN_STEREO;// 设置声道,立体声,双声道
20 | private static final int encodingBitRate = AudioFormat.ENCODING_PCM_16BIT;// 设置编码。脉冲编码调制(PCM)每个样品16位
21 | private static int recBufSize = 0;
22 | private static Thread recThread = null;// 录音线程
23 | private int playBufSize = 0;
24 |
25 | static void startRecorde(final int currenttime) {
26 | int initSuccess = initAAC(64000, frequency, 2);
27 |
28 | Log.d(TAG, "initSuccess" + ":" + initSuccess);
29 | if (initSuccess > 0) {
30 | startRec();
31 | Log.d(TAG, "inited successfully.");
32 | } else {
33 | Log.e(TAG, "inited failed.");
34 | }
35 |
36 | }
37 |
38 | // start record time
39 | private static void startRec() {
40 | // obtain min buf size
41 |
42 | recBufSize = getbuffersize();
43 | Log.v(TAG, "fdkaac input buffer size:" + recBufSize);
44 | recBufSize = AudioRecord.getMinBufferSize(frequency, channel, encodingBitRate);
45 |
46 | Log.v(TAG, "device supports minimum buffer size:" + recBufSize);
47 |
48 | // init record.
49 | mAudioRecord = new AudioRecord(AudioSource.VOICE_COMMUNICATION,//VOICE_COMMUNICATION will eliminate echo or noisy.
50 | frequency,
51 | channel,
52 | encodingBitRate,
53 | recBufSize);
54 |
55 | mAudioRecord.startRecording();
56 |
57 | isRecording = true;
58 |
59 | recThread = new Thread(new Runnable() {
60 | public void run() {
61 | byte data[] = new byte[recBufSize];
62 | int read = 0;
63 | while (isRecording) {
64 | read = mAudioRecord.read(data, 0, 4096);
65 |
66 | if (AudioRecord.ERROR_INVALID_OPERATION != read) {
67 | boolean success = encodeFrame(data);
68 |
69 | if (success) {
70 | // Log.d(TAG, "whiting file..");
71 | } else {
72 | Log.e(TAG, "aac write into file failure.");
73 | }
74 | }
75 | }
76 | }
77 | }, "AudioRecorder Thread");
78 |
79 | recThread.start();
80 | }
81 |
82 |
83 | static void stopRecorde() {
84 | if (null != mAudioRecord) {
85 | isRecording = false;
86 | mAudioRecord.stop();
87 | mAudioRecord.release();
88 | mAudioRecord = null;
89 | recThread = null;
90 | }
91 | }
92 |
93 | public native static int initAAC(int bitrate, int samplerate, int channels);
94 |
95 | public native static boolean encodeFrame(byte[] data);
96 |
97 | public native static int getbuffersize();
98 | }
99 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/java/io/github/brucewind/softcodec/AudioRecorder.java:
--------------------------------------------------------------------------------
1 | package io.github.brucewind.softcodec;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioRecord;
5 | import android.media.MediaRecorder;
6 | import android.media.MediaRecorder.AudioSource;
7 | import android.util.Log;
8 |
9 | /**
10 | * Obviously it is used to record audio.
11 | */
12 | public class AudioRecorder {
13 |
14 | static final String TAG = "AudioRecorder";
15 |
16 | private static AudioRecord mAudioRecord = null;
17 | private static boolean isRecording = false;// 录音标志位
18 | private static final int frequency = 44100;
19 | private static final int channel = AudioFormat.CHANNEL_IN_STEREO;// 设置声道,立体声,双声道
20 | private static final int encodingBitRate = AudioFormat.ENCODING_PCM_16BIT;// 设置编码。脉冲编码调制(PCM)每个样品16位
21 | private static int recBufSize = 0;
22 | private static Thread recThread = null;// 录音线程
23 | private int playBufSize = 0;
24 |
25 | static void startRecorde(final int currenttime) {
26 | int initSuccess = initAAC(64000, frequency, 2);
27 |
28 | Log.d(TAG, "initSuccess" + ":" + initSuccess);
29 | if (initSuccess > 0) {
30 | startRec();
31 | Log.d(TAG, "inited successfully.");
32 | } else {
33 | Log.e(TAG, "inited failed.");
34 | }
35 |
36 | }
37 |
38 | // start record time
39 | private static void startRec() {
40 | // obtain min buf size
41 |
42 | recBufSize = getbuffersize();
43 | Log.v(TAG, "fdkaac input buffer size:" + recBufSize);
44 | recBufSize = AudioRecord.getMinBufferSize(frequency, channel, encodingBitRate);
45 |
46 | Log.v(TAG, "device supports minimum buffer size:" + recBufSize);
47 |
48 | // init record.
49 | mAudioRecord = new AudioRecord(AudioSource.VOICE_COMMUNICATION,//VOICE_COMMUNICATION will eliminate echo or noisy.
50 | frequency,
51 | channel,
52 | encodingBitRate,
53 | recBufSize);
54 |
55 | mAudioRecord.startRecording();
56 |
57 | isRecording = true;
58 |
59 | recThread = new Thread(new Runnable() {
60 | public void run() {
61 | byte data[] = new byte[recBufSize];
62 | int read = 0;
63 | while (isRecording) {
64 | read = mAudioRecord.read(data, 0, 4096);
65 |
66 | if (AudioRecord.ERROR_INVALID_OPERATION != read) {
67 | boolean success = encodeFrame(data);
68 |
69 | if (success) {
70 | // Log.d(TAG, "whiting file..");
71 | } else {
72 | Log.e(TAG, "aac write into file failure.");
73 | }
74 | }
75 | }
76 | }
77 | }, "AudioRecorder Thread");
78 |
79 | recThread.start();
80 | }
81 |
82 |
83 | static void stopRecorde() {
84 | if (null != mAudioRecord) {
85 | isRecording = false;
86 | mAudioRecord.stop();
87 | mAudioRecord.release();
88 | mAudioRecord = null;
89 | recThread = null;
90 | }
91 | }
92 |
93 | public native static int initAAC(int bitrate, int samplerate, int channels);
94 |
95 | public native static boolean encodeFrame(byte[] data);
96 |
97 | public native static int getbuffersize();
98 | }
99 |
--------------------------------------------------------------------------------
/README_zh_cn.md:
--------------------------------------------------------------------------------
1 | # SoftCodec
2 |
3 | [](https://github.com/BruceWind/SoftCodec/actions/workflows/build.yml)
4 |
5 | - [x] 1. x264编码集成.
6 | - [x] 2. 推流到RTMP server.
7 | - [x] 3. openh264编码集成.
8 | - [ ] 4. 软件消除回声.
9 | - [ ] 5. 美颜 or 提升亮度 or HDR.
10 |
11 | ## 该仓库做了什么工作:
12 |
13 | ``` javascrpt
14 | phone
15 | +-----------------------+
16 | | |
17 | | |
18 | | +-----------+ |
19 | | | | | +----------------+ +----------------+
20 | | | Camera |-------->| YUV format A | -----> | YUV format B |
21 | | | | | +----------------+ +----------------+
22 | | +-----------+ | |
23 | | | |
24 | | | |
25 | | | v
26 | | | +------------+ +---------------+
27 | | | | | | |
28 | | | | YUV(NALs) |<------ | Codec |
29 | | | | | | |
30 | | | +------------+ +---------------+
31 | | | |
32 | | | |
33 | | | |
34 | | | |
35 | | | v
36 | | +-------------+ | +-------------+
37 | | | | | | |
38 | | | WIFI |<-------- | RTMP & FLV |
39 | | | | | | |
40 | | +-------------+ | +-------------+
41 | | | |
42 | +-----------|-----------+
43 | |
44 | | RTMP server
45 | | +-----------+
46 | | | |
47 | | | _____ |
48 | | | |_____| |
49 | +------------------->| ___ |
50 | | |___| |
51 | | |
52 | | |
53 | | |
54 | +-----------+
55 | ```
56 |
57 |
58 | ## Building & Testing
59 |
60 | **1. 编译**
61 |
62 | 目前gradle里配置了ndk版本是16,您无需手动配置下载NDK,运行编译命令时会自动执行,电脑无对应版本的ndk则会优先下载ndk,请注意网络环境。
63 |
64 | **2.建立RTMP server:**
65 |
66 | 您可能还没有RTMP服务器. 那么您需要自己建立一个rtmp服务器用于收发数据流。
67 |
68 | 我写了一篇blog教别人如何建立一个rtmp服务器:
69 | 这里是:[blog](https://github.com/BruceWind/BruceWind.github.io/blob/master/md/establish-RTMP-server-with-docker.md).
70 |
71 | **3. 测试推流**
72 |
73 | 修改`MainActivity`中如下代码, 使其指向你的RTMP流媒体服务器:
74 | ``` java
75 | private String mRtmpPushUrl = "rtmp://192.168.50.14/live/live";
76 | ```
77 | ---------------
78 | 需要补充的是:
79 | 1. `master` 分支是稳定版本的代码,若您需要开发中的代码,请移步其他分支。感谢您的star。
80 | 2. 该仓库的开源协议是[GPL](https://github.com/BruceWind/SoftCodec/blob/master/LINCENSE_CN),劳烦您遵守此协议。
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SoftCodec
2 |
3 | [](https://github.com/BruceWind/SoftCodec/actions/workflows/build.yml)
4 |
5 | [中文](https://github.com/BruceWind/SoftCodec/blob/master/README_zh_cn.md)
6 | - [x] 1. encode with x264.
7 | - [x] 2. push into RTMP server.
8 | - [x] 3. encode with openh264.
9 | - [ ] 4. echo cancellation in software. Maybe need libspeex.
10 |
11 | ## What It Does:
12 |
13 | click to expand.
14 |
15 | ``` javascrpt
16 | phone
17 | +-----------------------+
18 | | |
19 | | |
20 | | +-----------+ |
21 | | | | | +----------------+ +----------------+
22 | | | Camera |-------->| YUV format A | -----> | YUV format B |
23 | | | | | +----------------+ +----------------+
24 | | +-----------+ | |
25 | | | |
26 | | | |
27 | | | v
28 | | | +------------+ +---------------+
29 | | | | | | |
30 | | | | YUV(NALs) |<------ | Codec |
31 | | | | | | |
32 | | | +------------+ +---------------+
33 | | | |
34 | | | |
35 | | | |
36 | | | |
37 | | | v
38 | | +-------------+ | +-------------+
39 | | | | | | |
40 | | | WIFI |<-------- | RTMP & FLV |
41 | | | | | | |
42 | | +-------------+ | +-------------+
43 | | | |
44 | +-----------|-----------+
45 | |
46 | | RTMP server
47 | | +-----------+
48 | | | |
49 | | | _____ |
50 | | | |_____| |
51 | +------------------->| ___ |
52 | | |___| |
53 | | |
54 | | |
55 | | |
56 | +-----------+
57 | ```
58 |
59 |
60 |
61 | ## Building & Testing
62 |
63 | click to expand.
64 |
65 | **1. building**
66 |
67 | It depend on NDK 16, but you don't need to download manually.
68 | By the time you executed `./gradlew assembleDebug`, gradle will download it automatically in case
69 | your computer has no NDK 16.
70 |
71 | **2. Testing with a RTMP server:**
72 |
73 |
74 | You must have a RTMP server which receives stream app pushed. The RTMP server can also transfer data to video players.
75 |
76 | I had written a blog to teach someone else how to establish it.
77 | You can look into the [blog](https://github.com/BruceWind/BruceWind.github.io/blob/master/md/establish-RTMP-server-with-docker.md).
78 |
79 | **3. Pushing stream.**
80 |
81 | modify this code line below in `MainActivity` to point to your rtmp server:
82 | ``` java
83 | private String mRtmpPushUrl = "rtmp://192.168.50.14/live/live";
84 | ```
85 |
86 |
87 | ---------------
88 |
89 | In addition, `master` branch has all of stable codes, If you want to look code in development, checkout
90 | other branches.
91 |
92 |
93 | Take look at [CodecLibsBuildSH](https://github.com/BruceWind/CodecLibsBuildSH) in case you want to upgrade version of Codec.
94 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Android template
3 | # Built application files
4 | *.apk
5 | *.ap_
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 |
18 | # Gradle files
19 | .gradle/
20 | build/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | # Log Files
29 | *.log
30 |
31 | # Android Studio Navigation editor temp files
32 | .navigation/
33 |
34 | # Android Studio captures folder
35 | captures/
36 |
37 | # Intellij
38 | *.iml
39 | .idea/workspace.xml
40 | .idea/
41 | # Keystore files
42 | *.jks
43 |
44 | ### Android template
45 | # Built application files
46 | *.apk
47 | *.ap_
48 |
49 | # Files for the ART/Dalvik VM
50 | *.dex
51 |
52 | # Java class files
53 | *.class
54 |
55 | # Generated files
56 | bin/
57 | gen/
58 | out/
59 |
60 | # Gradle files
61 | .gradle/
62 | build/
63 |
64 | # Local configuration file (sdk path, etc)
65 | local.properties
66 |
67 | # Proguard folder generated by Eclipse
68 | proguard/
69 |
70 | # Log Files
71 | *.log
72 |
73 | # Android Studio Navigation editor temp files
74 | .navigation/
75 |
76 | # Android Studio captures folder
77 | captures/
78 |
79 | # Intellij
80 | *.iml
81 | .idea/workspace.xml
82 |
83 | # Keystore files
84 | *.jks
85 |
86 | ### CMake template
87 | CMakeLists.txt.user
88 | CMakeCache.txt
89 | CMakeFiles
90 | CMakeScripts
91 | Testing
92 | Makefile
93 | cmake_install.cmake
94 | install_manifest.txt
95 | compile_commands.json
96 | CTestTestfile.cmake
97 | _deps
98 |
99 | ### Android template
100 | # Built application files
101 | *.apk
102 | *.aar
103 | *.ap_
104 | *.aab
105 |
106 | # Files for the ART/Dalvik VM
107 | *.dex
108 |
109 | # Java class files
110 | *.class
111 |
112 | # Generated files
113 | bin/
114 | gen/
115 | out/
116 | # Uncomment the following line in case you need and you don't have the release build type files in your app
117 | # release/
118 |
119 | # Gradle files
120 | .gradle/
121 | build/
122 |
123 | # Local configuration file (sdk path, etc)
124 | local.properties
125 |
126 | # Proguard folder generated by Eclipse
127 | proguard/
128 |
129 | # Log Files
130 | *.log
131 |
132 | # Android Studio Navigation editor temp files
133 | .navigation/
134 |
135 | # Android Studio captures folder
136 | captures/
137 |
138 | # IntelliJ
139 | *.iml
140 | .idea/workspace.xml
141 | .idea/tasks.xml
142 | .idea/gradle.xml
143 | .idea/assetWizardSettings.xml
144 | .idea/dictionaries
145 | .idea/libraries
146 | # Android Studio 3 in .gitignore file.
147 | .idea/caches
148 | .idea/modules.xml
149 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
150 | .idea/navEditor.xml
151 |
152 | # Keystore files
153 | # Uncomment the following lines if you do not want to check your keystore files in.
154 | #*.jks
155 | #*.keystore
156 |
157 | # External native build folder generated in Android Studio 2.2 and later
158 | .externalNativeBuild
159 | .cxx/
160 |
161 | # Google Services (e.g. APIs or Firebase)
162 | # google-services.json
163 |
164 | # Freeline
165 | freeline.py
166 | freeline/
167 | freeline_project_description.json
168 |
169 | # fastlane
170 | fastlane/report.xml
171 | fastlane/Preview.html
172 | fastlane/screenshots
173 | fastlane/test_output
174 | fastlane/readme.md
175 |
176 | # Version control
177 | vcs.xml
178 |
179 | # lint
180 | lint/intermediates/
181 | lint/generated/
182 | lint/outputs/
183 | lint/tmp/
184 | # lint/reports/
185 |
186 | ### C++ template
187 | # Prerequisites
188 | *.d
189 |
190 | # Compiled Object files
191 | *.slo
192 | *.lo
193 | *.o
194 | *.obj
195 |
196 | # Precompiled Headers
197 | *.gch
198 | *.pch
199 |
200 | # Compiled Dynamic libraries
201 | *.so
202 | *.dylib
203 | *.dll
204 |
205 | # Fortran module files
206 | *.mod
207 | *.smod
208 |
209 | # Compiled Static libraries
210 | *.lai
211 | *.la
212 | *.lib
213 |
214 | # Executables
215 | *.exe
216 | *.out
217 | *.app
218 |
219 | ### C template
220 | # Prerequisites
221 | *.d
222 |
223 | # Object files
224 | *.o
225 | *.ko
226 | *.obj
227 | *.elf
228 |
229 | # Linker output
230 | *.ilk
231 | *.map
232 | *.exp
233 |
234 | # Precompiled Headers
235 | *.gch
236 | *.pch
237 |
238 | # Libraries
239 | *.lib
240 | *.la
241 | *.lo
242 |
243 | # Shared objects (inc. Windows DLLs)
244 | *.dll
245 | *.so
246 | *.so.*
247 | *.dylib
248 |
249 | # Executables
250 | *.exe
251 | *.out
252 | *.app
253 | *.i*86
254 | *.x86_64
255 | *.hex
256 |
257 | # Debug files
258 | *.dSYM/
259 | *.su
260 | *.idb
261 | *.pdb
262 |
263 | # Kernel Module Compile Results
264 | *.mod*
265 | *.cmd
266 | .tmp_versions/
267 | modules.order
268 | Module.symvers
269 | Mkfile.old
270 | dkms.conf
271 |
272 | .vscode
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/rtmp_sys.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_SYS_H__
2 | #define __RTMP_SYS_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | *
6 | * This file is part of librtmp.
7 | *
8 | * librtmp is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as
10 | * published by the Free Software Foundation; either version 2.1,
11 | * or (at your option) any later version.
12 | *
13 | * librtmp is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with librtmp see the file COPYING. If not, write to
20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 | * Boston, MA 02110-1301, USA.
22 | * http://www.gnu.org/copyleft/lgpl.html
23 | */
24 |
25 | #ifdef _WIN32
26 |
27 | #include
28 | #include
29 |
30 | #ifdef _MSC_VER /* MSVC */
31 | #define snprintf _snprintf
32 | #define strcasecmp stricmp
33 | #define strncasecmp strnicmp
34 | #define vsnprintf _vsnprintf
35 | #endif
36 |
37 | #define GetSockError() WSAGetLastError()
38 | #define SetSockError(e) WSASetLastError(e)
39 | #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
40 | #define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
41 | #define sleep(n) Sleep(n*1000)
42 | #define msleep(n) Sleep(n)
43 | #define SET_RCVTIMEO(tv,s) int tv = s*1000
44 | #else /* !_WIN32 */
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #define GetSockError() errno
54 | #define SetSockError(e) errno = e
55 | #undef closesocket
56 | #define closesocket(s) close(s)
57 | #define msleep(n) usleep(n*1000)
58 | #define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
59 | #endif
60 |
61 | #include "rtmp.h"
62 |
63 | #ifdef USE_POLARSSL
64 | #include
65 | #include
66 | #include
67 | #include
68 | #if POLARSSL_VERSION_NUMBER < 0x01010000
69 | #define havege_random havege_rand
70 | #endif
71 | #if POLARSSL_VERSION_NUMBER >= 0x01020000
72 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,ctx)
73 | #else
74 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,resume,timeout,ctx)
75 | #endif
76 | typedef struct tls_ctx {
77 | havege_state hs;
78 | ssl_session ssn;
79 | } tls_ctx;
80 | typedef struct tls_server_ctx {
81 | havege_state *hs;
82 | x509_cert cert;
83 | rsa_context key;
84 | ssl_session ssn;
85 | const char *dhm_P, *dhm_G;
86 | } tls_server_ctx;
87 |
88 | #define TLS_CTX tls_ctx *
89 | #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
90 | ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\
91 | ssl_set_rng(s, havege_random, &ctx->hs);\
92 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
93 | SSL_SET_SESSION(s, 1, 600, &ctx->ssn)
94 | #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
95 | ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\
96 | ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\
97 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
98 | SSL_SET_SESSION(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\
99 | ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\
100 | ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G)
101 | #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd)
102 | #define TLS_connect(s) ssl_handshake(s)
103 | #define TLS_accept(s) ssl_handshake(s)
104 | #define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l)
105 | #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l)
106 | #define TLS_shutdown(s) ssl_close_notify(s)
107 | #define TLS_close(s) ssl_free(s); free(s)
108 |
109 | #elif defined(USE_GNUTLS)
110 | #include
111 | typedef struct tls_ctx {
112 | gnutls_certificate_credentials_t cred;
113 | gnutls_priority_t prios;
114 | } tls_ctx;
115 | #define TLS_CTX tls_ctx *
116 | #define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred)
117 | #define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx)
118 | #define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd)
119 | #define TLS_connect(s) gnutls_handshake(s)
120 | #define TLS_accept(s) gnutls_handshake(s)
121 | #define TLS_read(s,b,l) gnutls_record_recv(s,b,l)
122 | #define TLS_write(s,b,l) gnutls_record_send(s,b,l)
123 | #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR)
124 | #define TLS_close(s) gnutls_deinit(s)
125 |
126 | #else /* USE_OPENSSL */
127 | #define TLS_CTX SSL_CTX *
128 | #define TLS_client(ctx,s) s = SSL_new(ctx)
129 | #define TLS_server(ctx,s) s = SSL_new(ctx)
130 | #define TLS_setfd(s,fd) SSL_set_fd(s,fd)
131 | #define TLS_connect(s) SSL_connect(s)
132 | #define TLS_accept(s) SSL_accept(s)
133 | #define TLS_read(s,b,l) SSL_read(s,b,l)
134 | #define TLS_write(s,b,l) SSL_write(s,b,l)
135 | #define TLS_shutdown(s) SSL_shutdown(s)
136 | #define TLS_close(s) SSL_free(s)
137 |
138 | #endif
139 | #endif
140 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/rtmp_sys.h:
--------------------------------------------------------------------------------
1 | #ifndef __RTMP_SYS_H__
2 | #define __RTMP_SYS_H__
3 | /*
4 | * Copyright (C) 2010 Howard Chu
5 | *
6 | * This file is part of librtmp.
7 | *
8 | * librtmp is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License as
10 | * published by the Free Software Foundation; either version 2.1,
11 | * or (at your option) any later version.
12 | *
13 | * librtmp is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public License
19 | * along with librtmp see the file COPYING. If not, write to
20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 | * Boston, MA 02110-1301, USA.
22 | * http://www.gnu.org/copyleft/lgpl.html
23 | */
24 |
25 | #ifdef _WIN32
26 |
27 | #include
28 | #include
29 |
30 | #ifdef _MSC_VER /* MSVC */
31 | #define snprintf _snprintf
32 | #define strcasecmp stricmp
33 | #define strncasecmp strnicmp
34 | #define vsnprintf _vsnprintf
35 | #endif
36 |
37 | #define GetSockError() WSAGetLastError()
38 | #define SetSockError(e) WSASetLastError(e)
39 | #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
40 | #define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
41 | #define sleep(n) Sleep(n*1000)
42 | #define msleep(n) Sleep(n)
43 | #define SET_RCVTIMEO(tv,s) int tv = s*1000
44 | #else /* !_WIN32 */
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #define GetSockError() errno
54 | #define SetSockError(e) errno = e
55 | #undef closesocket
56 | #define closesocket(s) close(s)
57 | #define msleep(n) usleep(n*1000)
58 | #define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
59 | #endif
60 |
61 | #include "rtmp.h"
62 |
63 | #ifdef USE_POLARSSL
64 | #include
65 | #include
66 | #include
67 | #include
68 | #if POLARSSL_VERSION_NUMBER < 0x01010000
69 | #define havege_random havege_rand
70 | #endif
71 | #if POLARSSL_VERSION_NUMBER >= 0x01020000
72 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,ctx)
73 | #else
74 | #define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,resume,timeout,ctx)
75 | #endif
76 | typedef struct tls_ctx {
77 | havege_state hs;
78 | ssl_session ssn;
79 | } tls_ctx;
80 | typedef struct tls_server_ctx {
81 | havege_state *hs;
82 | x509_cert cert;
83 | rsa_context key;
84 | ssl_session ssn;
85 | const char *dhm_P, *dhm_G;
86 | } tls_server_ctx;
87 |
88 | #define TLS_CTX tls_ctx *
89 | #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
90 | ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\
91 | ssl_set_rng(s, havege_random, &ctx->hs);\
92 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
93 | SSL_SET_SESSION(s, 1, 600, &ctx->ssn)
94 | #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
95 | ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\
96 | ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\
97 | ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
98 | SSL_SET_SESSION(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\
99 | ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\
100 | ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G)
101 | #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd)
102 | #define TLS_connect(s) ssl_handshake(s)
103 | #define TLS_accept(s) ssl_handshake(s)
104 | #define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l)
105 | #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l)
106 | #define TLS_shutdown(s) ssl_close_notify(s)
107 | #define TLS_close(s) ssl_free(s); free(s)
108 |
109 | #elif defined(USE_GNUTLS)
110 | #include
111 | typedef struct tls_ctx {
112 | gnutls_certificate_credentials_t cred;
113 | gnutls_priority_t prios;
114 | } tls_ctx;
115 | #define TLS_CTX tls_ctx *
116 | #define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred)
117 | #define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx)
118 | #define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd)
119 | #define TLS_connect(s) gnutls_handshake(s)
120 | #define TLS_accept(s) gnutls_handshake(s)
121 | #define TLS_read(s,b,l) gnutls_record_recv(s,b,l)
122 | #define TLS_write(s,b,l) gnutls_record_send(s,b,l)
123 | #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR)
124 | #define TLS_close(s) gnutls_deinit(s)
125 |
126 | #else /* USE_OPENSSL */
127 | #define TLS_CTX SSL_CTX *
128 | #define TLS_client(ctx,s) s = SSL_new(ctx)
129 | #define TLS_server(ctx,s) s = SSL_new(ctx)
130 | #define TLS_setfd(s,fd) SSL_set_fd(s,fd)
131 | #define TLS_connect(s) SSL_connect(s)
132 | #define TLS_accept(s) SSL_accept(s)
133 | #define TLS_read(s,b,l) SSL_read(s,b,l)
134 | #define TLS_write(s,b,l) SSL_write(s,b,l)
135 | #define TLS_shutdown(s) SSL_shutdown(s)
136 | #define TLS_close(s) SSL_free(s)
137 |
138 | #endif
139 | #endif
140 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/log.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008-2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "rtmp_sys.h"
31 | #include "log.h"
32 |
33 | #define MAX_PRINT_LEN 2048
34 |
35 | RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR;
36 |
37 | static int neednl;
38 |
39 | static FILE *fmsg;
40 |
41 | static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default;
42 |
43 | static const char *levels[] = {
44 | "CRIT", "ERROR", "WARNING", "INFO",
45 | "DEBUG", "DEBUG2"
46 | };
47 |
48 | static void rtmp_log_default(int level, const char *format, va_list vl)
49 | {
50 | char str[MAX_PRINT_LEN]="";
51 |
52 | vsnprintf(str, MAX_PRINT_LEN-1, format, vl);
53 |
54 | /* Filter out 'no-name' */
55 | if ( RTMP_debuglevel RTMP_debuglevel )
108 | return;
109 |
110 | ptr = line;
111 |
112 | for(i=0; i> 4)];
114 | *ptr++ = hexdig[0x0f & data[i]];
115 | if ((i & 0x0f) == 0x0f) {
116 | *ptr = '\0';
117 | ptr = line;
118 | RTMP_Log(level, "%s", line);
119 | } else {
120 | *ptr++ = ' ';
121 | }
122 | }
123 | if (i & 0x0f) {
124 | *ptr = '\0';
125 | RTMP_Log(level, "%s", line);
126 | }
127 | }
128 |
129 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len)
130 | {
131 | #define BP_OFFSET 9
132 | #define BP_GRAPH 60
133 | #define BP_LEN 80
134 | char line[BP_LEN];
135 | unsigned long i;
136 |
137 | if ( !data || level > RTMP_debuglevel )
138 | return;
139 |
140 | /* in case len is zero */
141 | line[0] = '\0';
142 |
143 | for ( i = 0 ; i < len ; i++ ) {
144 | int n = i % 16;
145 | unsigned off;
146 |
147 | if( !n ) {
148 | if( i ) RTMP_Log( level, "%s", line );
149 | memset( line, ' ', sizeof(line)-2 );
150 | line[sizeof(line)-2] = '\0';
151 |
152 | off = i % 0x0ffffU;
153 |
154 | line[2] = hexdig[0x0f & (off >> 12)];
155 | line[3] = hexdig[0x0f & (off >> 8)];
156 | line[4] = hexdig[0x0f & (off >> 4)];
157 | line[5] = hexdig[0x0f & off];
158 | line[6] = ':';
159 | }
160 |
161 | off = BP_OFFSET + n*3 + ((n >= 8)?1:0);
162 | line[off] = hexdig[0x0f & ( data[i] >> 4 )];
163 | line[off+1] = hexdig[0x0f & data[i]];
164 |
165 | off = BP_GRAPH + n + ((n >= 8)?1:0);
166 |
167 | if ( isprint( data[i] )) {
168 | line[BP_GRAPH + n] = data[i];
169 | } else {
170 | line[BP_GRAPH + n] = '.';
171 | }
172 | }
173 |
174 | RTMP_Log( level, "%s", line );
175 | }
176 |
177 | /* These should only be used by apps, never by the library itself */
178 | void RTMP_LogPrintf(const char *format, ...)
179 | {
180 | char str[MAX_PRINT_LEN]="";
181 | int len;
182 | va_list args;
183 | va_start(args, format);
184 | len = vsnprintf(str, MAX_PRINT_LEN-1, format, args);
185 | va_end(args);
186 |
187 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
188 | return;
189 |
190 | if ( !fmsg ) fmsg = stderr;
191 |
192 | if (neednl) {
193 | putc('\n', fmsg);
194 | neednl = 0;
195 | }
196 |
197 | if (len > MAX_PRINT_LEN-1)
198 | len = MAX_PRINT_LEN-1;
199 | fprintf(fmsg, "%s", str);
200 | if (str[len-1] == '\n')
201 | fflush(fmsg);
202 | }
203 |
204 | void RTMP_LogStatus(const char *format, ...)
205 | {
206 | char str[MAX_PRINT_LEN]="";
207 | va_list args;
208 | va_start(args, format);
209 | vsnprintf(str, MAX_PRINT_LEN-1, format, args);
210 | va_end(args);
211 |
212 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
213 | return;
214 |
215 | if ( !fmsg ) fmsg = stderr;
216 |
217 | fprintf(fmsg, "%s", str);
218 | fflush(fmsg);
219 | neednl = 1;
220 | }
221 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/log.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008-2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "rtmp_sys.h"
31 | #include "log.h"
32 |
33 | #define MAX_PRINT_LEN 2048
34 |
35 | RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR;
36 |
37 | static int neednl;
38 |
39 | static FILE *fmsg;
40 |
41 | static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default;
42 |
43 | static const char *levels[] = {
44 | "CRIT", "ERROR", "WARNING", "INFO",
45 | "DEBUG", "DEBUG2"
46 | };
47 |
48 | static void rtmp_log_default(int level, const char *format, va_list vl)
49 | {
50 | char str[MAX_PRINT_LEN]="";
51 |
52 | vsnprintf(str, MAX_PRINT_LEN-1, format, vl);
53 |
54 | /* Filter out 'no-name' */
55 | if ( RTMP_debuglevel RTMP_debuglevel )
108 | return;
109 |
110 | ptr = line;
111 |
112 | for(i=0; i> 4)];
114 | *ptr++ = hexdig[0x0f & data[i]];
115 | if ((i & 0x0f) == 0x0f) {
116 | *ptr = '\0';
117 | ptr = line;
118 | RTMP_Log(level, "%s", line);
119 | } else {
120 | *ptr++ = ' ';
121 | }
122 | }
123 | if (i & 0x0f) {
124 | *ptr = '\0';
125 | RTMP_Log(level, "%s", line);
126 | }
127 | }
128 |
129 | void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len)
130 | {
131 | #define BP_OFFSET 9
132 | #define BP_GRAPH 60
133 | #define BP_LEN 80
134 | char line[BP_LEN];
135 | unsigned long i;
136 |
137 | if ( !data || level > RTMP_debuglevel )
138 | return;
139 |
140 | /* in case len is zero */
141 | line[0] = '\0';
142 |
143 | for ( i = 0 ; i < len ; i++ ) {
144 | int n = i % 16;
145 | unsigned off;
146 |
147 | if( !n ) {
148 | if( i ) RTMP_Log( level, "%s", line );
149 | memset( line, ' ', sizeof(line)-2 );
150 | line[sizeof(line)-2] = '\0';
151 |
152 | off = i % 0x0ffffU;
153 |
154 | line[2] = hexdig[0x0f & (off >> 12)];
155 | line[3] = hexdig[0x0f & (off >> 8)];
156 | line[4] = hexdig[0x0f & (off >> 4)];
157 | line[5] = hexdig[0x0f & off];
158 | line[6] = ':';
159 | }
160 |
161 | off = BP_OFFSET + n*3 + ((n >= 8)?1:0);
162 | line[off] = hexdig[0x0f & ( data[i] >> 4 )];
163 | line[off+1] = hexdig[0x0f & data[i]];
164 |
165 | off = BP_GRAPH + n + ((n >= 8)?1:0);
166 |
167 | if ( isprint( data[i] )) {
168 | line[BP_GRAPH + n] = data[i];
169 | } else {
170 | line[BP_GRAPH + n] = '.';
171 | }
172 | }
173 |
174 | RTMP_Log( level, "%s", line );
175 | }
176 |
177 | /* These should only be used by apps, never by the library itself */
178 | void RTMP_LogPrintf(const char *format, ...)
179 | {
180 | char str[MAX_PRINT_LEN]="";
181 | int len;
182 | va_list args;
183 | va_start(args, format);
184 | len = vsnprintf(str, MAX_PRINT_LEN-1, format, args);
185 | va_end(args);
186 |
187 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
188 | return;
189 |
190 | if ( !fmsg ) fmsg = stderr;
191 |
192 | if (neednl) {
193 | putc('\n', fmsg);
194 | neednl = 0;
195 | }
196 |
197 | if (len > MAX_PRINT_LEN-1)
198 | len = MAX_PRINT_LEN-1;
199 | fprintf(fmsg, "%s", str);
200 | if (str[len-1] == '\n')
201 | fflush(fmsg);
202 | }
203 |
204 | void RTMP_LogStatus(const char *format, ...)
205 | {
206 | char str[MAX_PRINT_LEN]="";
207 | va_list args;
208 | va_start(args, format);
209 | vsnprintf(str, MAX_PRINT_LEN-1, format, args);
210 | va_end(args);
211 |
212 | if ( RTMP_debuglevel==RTMP_LOGCRIT )
213 | return;
214 |
215 | if ( !fmsg ) fmsg = stderr;
216 |
217 | fprintf(fmsg, "%s", str);
218 | fflush(fmsg);
219 | neednl = 1;
220 | }
221 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/aacEncode.c:
--------------------------------------------------------------------------------
1 | #include "aacEncode.h"
2 | #include "stdbool.h"
3 |
4 |
5 | AACOutput* fdkencode;
6 |
7 | #define LOG_TAG "android-fdkaac"
8 | #define LOGI(...) __android_log_print(4, LOG_TAG, __VA_ARGS__);
9 | #define LOGE(...) __android_log_print(6, LOG_TAG, __VA_ARGS__);
10 |
11 |
12 | jint Java_io_github_brucewind_softcodec_AudioRecorder_initAAC(JNIEnv* env, jobject thiz,
13 | jint bitrate, jint sample_rate, jint channels) {
14 |
15 | fdkencode=(AACOutput *) malloc(sizeof(AACOutput));
16 | fdkencode->channels=channels;
17 | fdkencode->samplerate=sample_rate;
18 | fdkencode->bitrate=bitrate;
19 |
20 | fdkencode->transMux = 2; //TODO ??
21 | fdkencode->afterburner = 1; //TODO ??
22 | fdkencode->channelLoader = 1; //TODO ??
23 | fdkencode->aot = 2; //aot类型。
24 |
25 | //先打开编码器,给handle 赋值。
26 | if (aacEncOpen(&fdkencode->handle, 0, channels) != AACENC_OK) {
27 | fprintf(stderr, "无法打开编码器\n");
28 | return -1;
29 | }
30 | //设置AOT值
31 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_AOT, fdkencode->aot)
32 | != AACENC_OK) {
33 | fprintf(stderr, "无法设置AOT值:%d\n", fdkencode->aot);
34 | return -2;
35 | }
36 |
37 | //设置采样频率
38 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_SAMPLERATE, sample_rate)
39 | != AACENC_OK) {
40 | fprintf(stderr, "无法设置采样频率\n");
41 | return -3;
42 | }
43 |
44 | //根据声道数设置声道模式。
45 | switch (channels) {
46 | case 1:
47 | fdkencode->mode = MODE_1;
48 | break;
49 | case 2:
50 | fdkencode->mode = MODE_2;
51 | break;
52 | default:
53 | fprintf(stderr, "不支持的声道数 %d\n", channels);
54 | return -4;
55 | }
56 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_CHANNELMODE,
57 | fdkencode->mode) != AACENC_OK) {
58 | fprintf(stderr, "无法设置声道模式\n");
59 | return -5;
60 | }
61 |
62 | //设置比特率
63 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_BITRATE, bitrate)
64 | != AACENC_OK) {
65 | fprintf(stderr, "无法设置比特率\n");
66 | return -6;
67 | }
68 |
69 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_TRANSMUX, 2)
70 | != AACENC_OK) {
71 | fprintf(stderr, "无法设置 ADTS transmux\n");
72 | return -7;
73 | }
74 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_AFTERBURNER,
75 | fdkencode->afterburner) != AACENC_OK) {
76 | fprintf(stderr, "无法设置 afterburner 模式\n");
77 | return -8;
78 | }
79 | if (aacEncEncode(fdkencode->handle, NULL, NULL, NULL, NULL) != AACENC_OK) {
80 | fprintf(stderr, "无法初始化aac编码器\n");
81 | return -9;
82 | }
83 | if (aacEncInfo(fdkencode->handle, &fdkencode->info) != AACENC_OK) {
84 | fprintf(stderr, "无法获取到编码器信息\n");
85 | return -10;
86 | }
87 |
88 | return 1;
89 |
90 | }
91 | jint Java_io_github_brucewind_softcodec_AudioRecorder_getbuffersize(JNIEnv* env, jobject thiz){
92 | int frameLength =fdkencode->info.frameLength; //每帧的长度
93 | int channels = fdkencode->channels; //获取声道数。
94 | int input_size = channels * 2 * frameLength; //计算每帧的大小
95 | fdkencode->input_size=input_size;
96 | return input_size;
97 | }
98 |
99 | jboolean Java_io_github_brucewind_softcodec_AudioRecorder_encodeFrame(JNIEnv *pEnv,jobject obj,jbyteArray pcmData) {
100 |
101 | int nArrLen = (*pEnv)->GetArrayLength(pEnv,pcmData);
102 | // if (fdkencode->input_size != nArrLen) {
103 | //// LOGE("预期输入长度和实际长度不一致: 预期输入长度:%d , 实际输入长度:%d", fdkencode->input_size, nArrLen);
104 | // }
105 |
106 |
107 | // 1字节 uint8_t // 2字节 uint16_t
108 | // uint8_t* input_buf = (uint8_t*) malloc(input_size);//分配输入空间
109 | jbyte* arrayBody = (*pEnv)->GetByteArrayElements(pEnv,pcmData, 0);
110 | uint8_t* input_buf = (uint8_t*) arrayBody;
111 | int16_t* convert_buf = (int16_t*) malloc(fdkencode->input_size); //分配转换空间
112 |
113 | int read = fdkencode->input_size;
114 | int i;
115 | //将8位的值转为16位。
116 | for ( i = 0; i < read / 2; i++) {
117 | const uint8_t* in = &input_buf[2 * i];
118 | convert_buf[i] = in[0] | (in[1] << 8);
119 | }
120 |
121 | AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
122 | AACENC_InArgs in_args = { 0 };
123 | AACENC_OutArgs out_args = { 0 };
124 | int in_identifier = IN_AUDIO_DATA;
125 | int in_size, in_elem_size;
126 | int out_identifier = OUT_BITSTREAM_DATA;
127 | int out_size, out_elem_size;
128 | void *in_ptr, *out_ptr;
129 | uint8_t outbuf[20480];
130 |
131 | if (read <= 0) {
132 | in_args.numInSamples = -1;
133 | } else {
134 | in_ptr = convert_buf;
135 | in_size = read;
136 | in_elem_size = 2;
137 |
138 | in_args.numInSamples = read / 2;
139 | in_buf.numBufs = 1;
140 | in_buf.bufs = &in_ptr;
141 | in_buf.bufferIdentifiers = &in_identifier;
142 | in_buf.bufSizes = &in_size;
143 | in_buf.bufElSizes = &in_elem_size;
144 | }
145 | out_ptr = outbuf;
146 | out_size = sizeof(outbuf);
147 | out_elem_size = 1;
148 | out_buf.numBufs = 1;
149 | out_buf.bufs = &out_ptr;
150 | out_buf.bufferIdentifiers = &out_identifier;
151 | out_buf.bufSizes = &out_size;
152 | out_buf.bufElSizes = &out_elem_size;
153 |
154 | bool success = aacEncoderProcess(&in_buf, &out_buf, &in_args,&out_args);
155 |
156 | if (success) {
157 | if (out_args.numOutBytes != 0) {
158 |
159 | if(fdkencode->first==0){
160 | // char asc[2];
161 | // asc[0] = 0x10 | ((4 >> 1) & 0x3);
162 | // asc[1] = ((4 & 0x1) << 7) | ((2 & 0xF) << 3);
163 | // send_rtmp_audio_spec((unsigned char*)asc, 2);
164 | send_rtmp_audio_spec(fdkencode->info.confBuf,fdkencode->info.confSize);
165 | fdkencode->first = 1;
166 | }
167 | send_rtmp_audio(outbuf,out_args.numOutBytes,getSystemTime());
168 | }
169 | }
170 |
171 | free(convert_buf);
172 | return 1;
173 | }
174 |
175 | bool aacEncoderProcess(AACENC_BufDesc* in_buf,
176 | AACENC_BufDesc* out_buf,
177 | AACENC_InArgs* in_args,
178 | AACENC_OutArgs* out_args) {
179 |
180 | AACENC_ERROR err;
181 |
182 | if ((err = aacEncEncode(fdkencode->handle, in_buf, out_buf, in_args, out_args))
183 | != AACENC_OK) {
184 | if (err == AACENC_ENCODE_EOF) {
185 | //结尾,正常结束
186 | return true;
187 | }
188 | fprintf(stderr, "编码失败!!err = %d \n", err);
189 | return false;
190 | }
191 | return true;
192 | }
193 |
194 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/softcodec/aacEncode.c:
--------------------------------------------------------------------------------
1 | #include "aacEncode.h"
2 | #include "stdbool.h"
3 |
4 |
5 | AACOutput* fdkencode;
6 |
7 | #define LOG_TAG "android-fdkaac"
8 | #define LOGI(...) __android_log_print(4, LOG_TAG, __VA_ARGS__);
9 | #define LOGE(...) __android_log_print(6, LOG_TAG, __VA_ARGS__);
10 |
11 |
12 | jint Java_io_github_brucewind_softcodec_AudioRecorder_initAAC(JNIEnv* env, jobject thiz,
13 | jint bitrate, jint sample_rate, jint channels) {
14 |
15 | fdkencode=(AACOutput *) malloc(sizeof(AACOutput));
16 | fdkencode->channels=channels;
17 | fdkencode->samplerate=sample_rate;
18 | fdkencode->bitrate=bitrate;
19 |
20 | fdkencode->transMux = 2; //TODO ??
21 | fdkencode->afterburner = 1; //TODO ??
22 | fdkencode->channelLoader = 1; //TODO ??
23 | fdkencode->aot = 2; //aot类型。
24 |
25 | //先打开编码器,给handle 赋值。
26 | if (aacEncOpen(&fdkencode->handle, 0, channels) != AACENC_OK) {
27 | fprintf(stderr, "无法打开编码器\n");
28 | return -1;
29 | }
30 | //设置AOT值
31 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_AOT, fdkencode->aot)
32 | != AACENC_OK) {
33 | fprintf(stderr, "无法设置AOT值:%d\n", fdkencode->aot);
34 | return -2;
35 | }
36 |
37 | //设置采样频率
38 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_SAMPLERATE, sample_rate)
39 | != AACENC_OK) {
40 | fprintf(stderr, "无法设置采样频率\n");
41 | return -3;
42 | }
43 |
44 | //根据声道数设置声道模式。
45 | switch (channels) {
46 | case 1:
47 | fdkencode->mode = MODE_1;
48 | break;
49 | case 2:
50 | fdkencode->mode = MODE_2;
51 | break;
52 | default:
53 | fprintf(stderr, "不支持的声道数 %d\n", channels);
54 | return -4;
55 | }
56 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_CHANNELMODE,
57 | fdkencode->mode) != AACENC_OK) {
58 | fprintf(stderr, "无法设置声道模式\n");
59 | return -5;
60 | }
61 |
62 | //设置比特率
63 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_BITRATE, bitrate)
64 | != AACENC_OK) {
65 | fprintf(stderr, "无法设置比特率\n");
66 | return -6;
67 | }
68 |
69 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_TRANSMUX, 2)
70 | != AACENC_OK) {
71 | fprintf(stderr, "无法设置 ADTS transmux\n");
72 | return -7;
73 | }
74 | if (aacEncoder_SetParam(fdkencode->handle, AACENC_AFTERBURNER,
75 | fdkencode->afterburner) != AACENC_OK) {
76 | fprintf(stderr, "无法设置 afterburner 模式\n");
77 | return -8;
78 | }
79 | if (aacEncEncode(fdkencode->handle, NULL, NULL, NULL, NULL) != AACENC_OK) {
80 | fprintf(stderr, "无法初始化aac编码器\n");
81 | return -9;
82 | }
83 | if (aacEncInfo(fdkencode->handle, &fdkencode->info) != AACENC_OK) {
84 | fprintf(stderr, "无法获取到编码器信息\n");
85 | return -10;
86 | }
87 |
88 | return 1;
89 |
90 | }
91 | jint Java_io_github_brucewind_softcodec_AudioRecorder_getbuffersize(JNIEnv* env, jobject thiz){
92 | int frameLength =fdkencode->info.frameLength; //每帧的长度
93 | int channels = fdkencode->channels; //获取声道数。
94 | int input_size = channels * 2 * frameLength; //计算每帧的大小
95 | fdkencode->input_size=input_size;
96 | return input_size;
97 | }
98 |
99 | jboolean Java_io_github_brucewind_softcodec_AudioRecorder_encodeFrame(JNIEnv *pEnv,jobject obj,jbyteArray pcmData) {
100 |
101 | int nArrLen = (*pEnv)->GetArrayLength(pEnv,pcmData);
102 | // if (fdkencode->input_size != nArrLen) {
103 | //// LOGE("预期输入长度和实际长度不一致: 预期输入长度:%d , 实际输入长度:%d", fdkencode->input_size, nArrLen);
104 | // }
105 |
106 |
107 | // 1字节 uint8_t // 2字节 uint16_t
108 | // uint8_t* input_buf = (uint8_t*) malloc(input_size);//分配输入空间
109 | jbyte* arrayBody = (*pEnv)->GetByteArrayElements(pEnv,pcmData, 0);
110 | uint8_t* input_buf = (uint8_t*) arrayBody;
111 | int16_t* convert_buf = (int16_t*) malloc(fdkencode->input_size); //分配转换空间
112 |
113 | int read = fdkencode->input_size;
114 | int i;
115 | //将8位的值转为16位。
116 | for ( i = 0; i < read / 2; i++) {
117 | const uint8_t* in = &input_buf[2 * i];
118 | convert_buf[i] = in[0] | (in[1] << 8);
119 | }
120 |
121 | AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
122 | AACENC_InArgs in_args = { 0 };
123 | AACENC_OutArgs out_args = { 0 };
124 | int in_identifier = IN_AUDIO_DATA;
125 | int in_size, in_elem_size;
126 | int out_identifier = OUT_BITSTREAM_DATA;
127 | int out_size, out_elem_size;
128 | void *in_ptr, *out_ptr;
129 | uint8_t outbuf[20480];
130 |
131 | if (read <= 0) {
132 | in_args.numInSamples = -1;
133 | } else {
134 | in_ptr = convert_buf;
135 | in_size = read;
136 | in_elem_size = 2;
137 |
138 | in_args.numInSamples = read / 2;
139 | in_buf.numBufs = 1;
140 | in_buf.bufs = &in_ptr;
141 | in_buf.bufferIdentifiers = &in_identifier;
142 | in_buf.bufSizes = &in_size;
143 | in_buf.bufElSizes = &in_elem_size;
144 | }
145 | out_ptr = outbuf;
146 | out_size = sizeof(outbuf);
147 | out_elem_size = 1;
148 | out_buf.numBufs = 1;
149 | out_buf.bufs = &out_ptr;
150 | out_buf.bufferIdentifiers = &out_identifier;
151 | out_buf.bufSizes = &out_size;
152 | out_buf.bufElSizes = &out_elem_size;
153 |
154 | bool success = aacEncoderProcess(&in_buf, &out_buf, &in_args,&out_args);
155 |
156 | if (success) {
157 | if (out_args.numOutBytes != 0) {
158 |
159 | if(fdkencode->first==0){
160 | // char asc[2];
161 | // asc[0] = 0x10 | ((4 >> 1) & 0x3);
162 | // asc[1] = ((4 & 0x1) << 7) | ((2 & 0xF) << 3);
163 | // send_rtmp_audio_spec((unsigned char*)asc, 2);
164 | send_rtmp_audio_spec(fdkencode->info.confBuf,fdkencode->info.confSize);
165 | fdkencode->first = 1;
166 | }
167 | send_rtmp_audio(outbuf,out_args.numOutBytes,getSystemTime());
168 | }
169 | }
170 |
171 | free(convert_buf);
172 | return 1;
173 | }
174 |
175 | bool aacEncoderProcess(AACENC_BufDesc* in_buf,
176 | AACENC_BufDesc* out_buf,
177 | AACENC_InArgs* in_args,
178 | AACENC_OutArgs* out_args) {
179 |
180 | AACENC_ERROR err;
181 |
182 | if ((err = aacEncEncode(fdkencode->handle, in_buf, out_buf, in_args, out_args))
183 | != AACENC_OK) {
184 | if (err == AACENC_ENCODE_EOF) {
185 | //结尾,正常结束
186 | return true;
187 | }
188 | fprintf(stderr, "编码失败!!err = %d \n", err);
189 | return false;
190 | }
191 | return true;
192 | }
193 |
194 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/amf.h:
--------------------------------------------------------------------------------
1 | #ifndef __AMF_H__
2 | #define __AMF_H__
3 | /*
4 | * Copyright (C) 2005-2008 Team XBMC
5 | * http://www.xbmc.org
6 | * Copyright (C) 2008-2009 Andrej Stepanchuk
7 | * Copyright (C) 2009-2010 Howard Chu
8 | *
9 | * This file is part of librtmp.
10 | *
11 | * librtmp is free software; you can redistribute it and/or modify
12 | * it under the terms of the GNU Lesser General Public License as
13 | * published by the Free Software Foundation; either version 2.1,
14 | * or (at your option) any later version.
15 | *
16 | * librtmp is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU Lesser General Public License
22 | * along with librtmp see the file COPYING. If not, write to
23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 | * Boston, MA 02110-1301, USA.
25 | * http://www.gnu.org/copyleft/lgpl.html
26 | */
27 |
28 | #include
29 |
30 | #ifndef TRUE
31 | #define TRUE 1
32 | #define FALSE 0
33 | #endif
34 |
35 | #ifdef __cplusplus
36 | extern "C"
37 | {
38 | #endif
39 |
40 | typedef enum
41 | { AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT,
42 | AMF_MOVIECLIP, /* reserved, not used */
43 | AMF_NULL, AMF_UNDEFINED, AMF_REFERENCE, AMF_ECMA_ARRAY, AMF_OBJECT_END,
44 | AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED,
45 | AMF_RECORDSET, /* reserved, not used */
46 | AMF_XML_DOC, AMF_TYPED_OBJECT,
47 | AMF_AVMPLUS, /* switch to AMF3 */
48 | AMF_INVALID = 0xff
49 | } AMFDataType;
50 |
51 | typedef enum
52 | { AMF3_UNDEFINED = 0, AMF3_NULL, AMF3_FALSE, AMF3_TRUE,
53 | AMF3_INTEGER, AMF3_DOUBLE, AMF3_STRING, AMF3_XML_DOC, AMF3_DATE,
54 | AMF3_ARRAY, AMF3_OBJECT, AMF3_XML, AMF3_BYTE_ARRAY
55 | } AMF3DataType;
56 |
57 | typedef struct AVal
58 | {
59 | char *av_val;
60 | int av_len;
61 | } AVal;
62 | #define AVC(str) {str,sizeof(str)-1}
63 | #define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))
64 |
65 | struct AMFObjectProperty;
66 |
67 | typedef struct AMFObject
68 | {
69 | int o_num;
70 | struct AMFObjectProperty *o_props;
71 | } AMFObject;
72 |
73 | typedef struct AMFObjectProperty
74 | {
75 | AVal p_name;
76 | AMFDataType p_type;
77 | union
78 | {
79 | double p_number;
80 | AVal p_aval;
81 | AMFObject p_object;
82 | } p_vu;
83 | int16_t p_UTCoffset;
84 | } AMFObjectProperty;
85 |
86 | char *AMF_EncodeString(char *output, char *outend, const AVal * str);
87 | char *AMF_EncodeNumber(char *output, char *outend, double dVal);
88 | char *AMF_EncodeInt16(char *output, char *outend, short nVal);
89 | char *AMF_EncodeInt24(char *output, char *outend, int nVal);
90 | char *AMF_EncodeInt32(char *output, char *outend, int nVal);
91 | char *AMF_EncodeBoolean(char *output, char *outend, int bVal);
92 |
93 | /* Shortcuts for AMFProp_Encode */
94 | char *AMF_EncodeNamedString(char *output, char *outend, const AVal * name, const AVal * value);
95 | char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal * name, double dVal);
96 | char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal * name, int bVal);
97 |
98 | unsigned short AMF_DecodeInt16(const char *data);
99 | unsigned int AMF_DecodeInt24(const char *data);
100 | unsigned int AMF_DecodeInt32(const char *data);
101 | void AMF_DecodeString(const char *data, AVal * str);
102 | void AMF_DecodeLongString(const char *data, AVal * str);
103 | int AMF_DecodeBoolean(const char *data);
104 | double AMF_DecodeNumber(const char *data);
105 |
106 | char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd);
107 | char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
108 | char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
109 |
110 | int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize,
111 | int bDecodeName);
112 | int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize,
113 | int nArrayLen, int bDecodeName);
114 | int AMF3_Decode(AMFObject * obj, const char *pBuffer, int nSize,
115 | int bDecodeName);
116 | void AMF_Dump(AMFObject * obj);
117 | void AMF_Reset(AMFObject * obj);
118 |
119 | void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop);
120 | int AMF_CountProp(AMFObject * obj);
121 | AMFObjectProperty *AMF_GetProp(AMFObject * obj, const AVal * name,
122 | int nIndex);
123 |
124 | AMFDataType AMFProp_GetType(AMFObjectProperty * prop);
125 | void AMFProp_SetNumber(AMFObjectProperty * prop, double dval);
126 | void AMFProp_SetBoolean(AMFObjectProperty * prop, int bflag);
127 | void AMFProp_SetString(AMFObjectProperty * prop, AVal * str);
128 | void AMFProp_SetObject(AMFObjectProperty * prop, AMFObject * obj);
129 |
130 | void AMFProp_GetName(AMFObjectProperty * prop, AVal * name);
131 | void AMFProp_SetName(AMFObjectProperty * prop, AVal * name);
132 | double AMFProp_GetNumber(AMFObjectProperty * prop);
133 | int AMFProp_GetBoolean(AMFObjectProperty * prop);
134 | void AMFProp_GetString(AMFObjectProperty * prop, AVal * str);
135 | void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj);
136 |
137 | int AMFProp_IsValid(AMFObjectProperty * prop);
138 |
139 | char *AMFProp_Encode(AMFObjectProperty * prop, char *pBuffer, char *pBufEnd);
140 | int AMF3Prop_Decode(AMFObjectProperty * prop, const char *pBuffer,
141 | int nSize, int bDecodeName);
142 | int AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer,
143 | int nSize, int bDecodeName);
144 |
145 | void AMFProp_Dump(AMFObjectProperty * prop);
146 | void AMFProp_Reset(AMFObjectProperty * prop);
147 |
148 | typedef struct AMF3ClassDef
149 | {
150 | AVal cd_name;
151 | char cd_externalizable;
152 | char cd_dynamic;
153 | int cd_num;
154 | AVal *cd_props;
155 | } AMF3ClassDef;
156 |
157 | void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop);
158 | AVal *AMF3CD_GetProp(AMF3ClassDef * cd, int idx);
159 |
160 | #ifdef __cplusplus
161 | }
162 | #endif
163 |
164 | #endif /* __AMF_H__ */
165 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/amf.h:
--------------------------------------------------------------------------------
1 | #ifndef __AMF_H__
2 | #define __AMF_H__
3 | /*
4 | * Copyright (C) 2005-2008 Team XBMC
5 | * http://www.xbmc.org
6 | * Copyright (C) 2008-2009 Andrej Stepanchuk
7 | * Copyright (C) 2009-2010 Howard Chu
8 | *
9 | * This file is part of librtmp.
10 | *
11 | * librtmp is free software; you can redistribute it and/or modify
12 | * it under the terms of the GNU Lesser General Public License as
13 | * published by the Free Software Foundation; either version 2.1,
14 | * or (at your option) any later version.
15 | *
16 | * librtmp is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU Lesser General Public License
22 | * along with librtmp see the file COPYING. If not, write to
23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 | * Boston, MA 02110-1301, USA.
25 | * http://www.gnu.org/copyleft/lgpl.html
26 | */
27 |
28 | #include
29 |
30 | #ifndef TRUE
31 | #define TRUE 1
32 | #define FALSE 0
33 | #endif
34 |
35 | #ifdef __cplusplus
36 | extern "C"
37 | {
38 | #endif
39 |
40 | typedef enum
41 | { AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT,
42 | AMF_MOVIECLIP, /* reserved, not used */
43 | AMF_NULL, AMF_UNDEFINED, AMF_REFERENCE, AMF_ECMA_ARRAY, AMF_OBJECT_END,
44 | AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED,
45 | AMF_RECORDSET, /* reserved, not used */
46 | AMF_XML_DOC, AMF_TYPED_OBJECT,
47 | AMF_AVMPLUS, /* switch to AMF3 */
48 | AMF_INVALID = 0xff
49 | } AMFDataType;
50 |
51 | typedef enum
52 | { AMF3_UNDEFINED = 0, AMF3_NULL, AMF3_FALSE, AMF3_TRUE,
53 | AMF3_INTEGER, AMF3_DOUBLE, AMF3_STRING, AMF3_XML_DOC, AMF3_DATE,
54 | AMF3_ARRAY, AMF3_OBJECT, AMF3_XML, AMF3_BYTE_ARRAY
55 | } AMF3DataType;
56 |
57 | typedef struct AVal
58 | {
59 | char *av_val;
60 | int av_len;
61 | } AVal;
62 | #define AVC(str) {str,sizeof(str)-1}
63 | #define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))
64 |
65 | struct AMFObjectProperty;
66 |
67 | typedef struct AMFObject
68 | {
69 | int o_num;
70 | struct AMFObjectProperty *o_props;
71 | } AMFObject;
72 |
73 | typedef struct AMFObjectProperty
74 | {
75 | AVal p_name;
76 | AMFDataType p_type;
77 | union
78 | {
79 | double p_number;
80 | AVal p_aval;
81 | AMFObject p_object;
82 | } p_vu;
83 | int16_t p_UTCoffset;
84 | } AMFObjectProperty;
85 |
86 | char *AMF_EncodeString(char *output, char *outend, const AVal * str);
87 | char *AMF_EncodeNumber(char *output, char *outend, double dVal);
88 | char *AMF_EncodeInt16(char *output, char *outend, short nVal);
89 | char *AMF_EncodeInt24(char *output, char *outend, int nVal);
90 | char *AMF_EncodeInt32(char *output, char *outend, int nVal);
91 | char *AMF_EncodeBoolean(char *output, char *outend, int bVal);
92 |
93 | /* Shortcuts for AMFProp_Encode */
94 | char *AMF_EncodeNamedString(char *output, char *outend, const AVal * name, const AVal * value);
95 | char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal * name, double dVal);
96 | char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal * name, int bVal);
97 |
98 | unsigned short AMF_DecodeInt16(const char *data);
99 | unsigned int AMF_DecodeInt24(const char *data);
100 | unsigned int AMF_DecodeInt32(const char *data);
101 | void AMF_DecodeString(const char *data, AVal * str);
102 | void AMF_DecodeLongString(const char *data, AVal * str);
103 | int AMF_DecodeBoolean(const char *data);
104 | double AMF_DecodeNumber(const char *data);
105 |
106 | char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd);
107 | char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
108 | char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
109 |
110 | int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize,
111 | int bDecodeName);
112 | int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize,
113 | int nArrayLen, int bDecodeName);
114 | int AMF3_Decode(AMFObject * obj, const char *pBuffer, int nSize,
115 | int bDecodeName);
116 | void AMF_Dump(AMFObject * obj);
117 | void AMF_Reset(AMFObject * obj);
118 |
119 | void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop);
120 | int AMF_CountProp(AMFObject * obj);
121 | AMFObjectProperty *AMF_GetProp(AMFObject * obj, const AVal * name,
122 | int nIndex);
123 |
124 | AMFDataType AMFProp_GetType(AMFObjectProperty * prop);
125 | void AMFProp_SetNumber(AMFObjectProperty * prop, double dval);
126 | void AMFProp_SetBoolean(AMFObjectProperty * prop, int bflag);
127 | void AMFProp_SetString(AMFObjectProperty * prop, AVal * str);
128 | void AMFProp_SetObject(AMFObjectProperty * prop, AMFObject * obj);
129 |
130 | void AMFProp_GetName(AMFObjectProperty * prop, AVal * name);
131 | void AMFProp_SetName(AMFObjectProperty * prop, AVal * name);
132 | double AMFProp_GetNumber(AMFObjectProperty * prop);
133 | int AMFProp_GetBoolean(AMFObjectProperty * prop);
134 | void AMFProp_GetString(AMFObjectProperty * prop, AVal * str);
135 | void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj);
136 |
137 | int AMFProp_IsValid(AMFObjectProperty * prop);
138 |
139 | char *AMFProp_Encode(AMFObjectProperty * prop, char *pBuffer, char *pBufEnd);
140 | int AMF3Prop_Decode(AMFObjectProperty * prop, const char *pBuffer,
141 | int nSize, int bDecodeName);
142 | int AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer,
143 | int nSize, int bDecodeName);
144 |
145 | void AMFProp_Dump(AMFObjectProperty * prop);
146 | void AMFProp_Reset(AMFObjectProperty * prop);
147 |
148 | typedef struct AMF3ClassDef
149 | {
150 | AVal cd_name;
151 | char cd_externalizable;
152 | char cd_dynamic;
153 | int cd_num;
154 | AVal *cd_props;
155 | } AMF3ClassDef;
156 |
157 | void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop);
158 | AVal *AMF3CD_GetProp(AMF3ClassDef * cd, int idx);
159 |
160 | #ifdef __cplusplus
161 | }
162 | #endif
163 |
164 | #endif /* __AMF_H__ */
165 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/h264Encoder.c:
--------------------------------------------------------------------------------
1 |
2 | #include "h264Encoder.h"
3 | #include "h264_encoder_log.h"
4 |
5 | typedef struct {
6 | x264_param_t *param;
7 | x264_t *handle;
8 | x264_picture_t *picture;
9 | x264_nal_t *nal;
10 |
11 | } Encoder;
12 |
13 | unsigned char sps[30];
14 | unsigned char pps[10];
15 | int first = 0;
16 | int sps_len;
17 | int pps_len;
18 | #define RC_MARGIN 10000 /*bits per sec*/
19 | JNIEXPORT jlong
20 | Java_io_github_brucewind_softcodec_StreamHelper_compressBegin(JNIEnv *env,
21 | jobject thiz,
22 | jint width,
23 | jint height,
24 | jint bitrate,
25 | jint fps) {
26 |
27 |
28 | Encoder *en = (Encoder *) malloc(sizeof(Encoder));
29 | en->param = (x264_param_t *) malloc(sizeof(x264_param_t));
30 | en->picture = (x264_picture_t *) malloc(sizeof(x264_picture_t));
31 | x264_param_default(en->param); //set default param
32 | x264_param_default_preset(en->param,
33 | "veryfast",
34 | "zerolatency"); //set encoder params
35 | en->param->i_width = width;
36 | en->param->i_height = height;
37 | en->param->i_threads = 1;/* encode multiple frames in parallel */
38 | en->param->b_sliced_threads = 1;
39 | en->param->i_bframe_adaptive = X264_B_ADAPT_FAST;
40 | en->param->i_bframe_pyramid = X264_B_PYRAMID_NONE; /*允许部分B为参考帧,可选值为0,1,2 */
41 | en->param->b_intra_refresh = 0; //用周期帧内刷新替代IDR
42 | en->param->analyse.i_trellis =
43 | 1; /* Trellis量化,对每个8x8的块寻找合适的量化值,需要CABAC,默认0 0:关闭1:只在最后编码时使用2:一直使用*/
44 | en->param->analyse.b_chroma_me = 1;/* 亚像素色度运动估计和P帧的模式选择 */
45 | en->param->b_interlaced = 0;/* 隔行扫描 */
46 | en->param->analyse.b_transform_8x8 = 1;/* 帧间分区*/
47 | en->param->rc.f_qcompress = 0;/* 0.0 => cbr, 1.0 => constant qp */
48 | en->param->i_frame_reference = 4;/*参考帧的最大帧数。*/
49 | en->param->i_bframe = 0; /*两个参考帧之间的B帧数目*/
50 | en->param->analyse.i_me_range = 16;/* 整像素运动估计搜索范围 (from predicted mv) */
51 | en->param->analyse.i_me_method = X264_ME_DIA;/* 运动估计算法 (X264_ME_*)*/
52 | en->param->rc.i_lookahead = 0;
53 | en->param->i_keyint_max = 30;/* 在此间隔设置IDR关键帧(每过多少帧设置一个IDR帧) */
54 | en->param->i_scenecut_threshold = 40;/*如何积极地插入额外的I帧 */
55 | en->param->rc.i_qp_min = 10; //关键帧最小间隔
56 | en->param->rc.i_qp_max = 50; //关键帧最大间隔
57 | en->param->rc.i_qp_constant = 20;
58 | en->param->rc.i_bitrate = bitrate; /*设置平均码率 */
59 | en->param->i_fps_num = fps;/*帧率*/
60 | en->param->i_fps_den = 1;/*用两个整型的数的比值,来表示帧率*/
61 | en->param->b_annexb = 1; //different from AVCC structure
62 | en->param->b_cabac = 0;
63 | en->param->rc.i_rc_method =
64 | X264_RC_ABR; //参数i_rc_method表示码率控制,CQP(恒定质量),CRF(恒定码率),ABR(平均码率)
65 |
66 | x264_param_apply_profile(en->param, "baseline");
67 |
68 | if ((en->handle = x264_encoder_open(en->param)) == 0) {
69 | return 0;
70 | }
71 | en->picture->i_type = X264_TYPE_AUTO;
72 | //create a new pic
73 | x264_picture_alloc(en->picture, X264_CSP_I420, en->param->i_width,
74 | en->param->i_height);
75 |
76 | return (jlong) en;
77 |
78 | }
79 |
80 | /**
81 | * When compress end, clear some resource
82 | */
83 | JNIEXPORT jint
84 | Java_io_github_brucewind_softcodec_StreamHelper_compressEnd(JNIEnv *env,
85 | jobject thiz,
86 | jlong handle) {
87 | Encoder *en = (Encoder *) handle;
88 | ALOGE("begin free!");
89 | if (en->picture) {
90 | ALOGE("begin free picture");
91 | x264_picture_clean(en->picture);
92 | free(en->picture);
93 | en->picture = 0;
94 | }
95 |
96 | ALOGE("after free picture");
97 |
98 | if (en->param) {
99 | free(en->param);
100 | en->param = 0;
101 | }
102 |
103 | ALOGE("after free param");
104 |
105 | if (en->handle) {
106 | x264_encoder_close(en->handle);
107 | }
108 | ALOGE("after close encoder");
109 |
110 | free(en);
111 |
112 | ALOGE("after free encoder");
113 |
114 | return 0;
115 | }
116 |
117 | /**
118 | * There are two steps:
119 | * 1. compressing the buffer data into serveral NALUs;
120 | * 2. transferring the NALUs to RTMP server.
121 | */
122 | JNIEXPORT jint Java_io_github_brucewind_softcodec_StreamHelper_compressBuffer(
123 | JNIEnv *env,
124 | jobject thiz,
125 | jlong handler,//it is a pointer.
126 | jbyteArray in,
127 | jint input_size,
128 | jbyteArray out) {
129 |
130 |
131 | if (!isConnected())
132 | return 0;
133 |
134 |
135 | //find initialized encode by pointer address.
136 | Encoder *en = (Encoder *) handler;
137 | x264_picture_t pic_out;
138 | int i_data = 0;
139 | int count_of_NALU = -1;//A frame may be separated into saveral NALU.
140 | int result = 0;
141 | int i = 0;
142 | int i_frame_size = 0;
143 | int j = 0;
144 | int nPix = 0;
145 |
146 | jbyte *nv12_buf = (jbyte *) (*env)->GetByteArrayElements(env, in, 0);
147 | jbyte *h264_buf = (jbyte *) (*env)->GetByteArrayElements(env, out, 0);
148 | unsigned char *pTemp = h264_buf;
149 | int nPicSize = en->param->i_width * en->param->i_height;
150 |
151 | /**
152 | * YUV => 4:2:0
153 | * YYYY
154 | * YYYY
155 | * UVUV
156 | */
157 | jbyte *y = en->picture->img.plane[0];
158 | jbyte *v = en->picture->img.plane[1];
159 | jbyte *u = en->picture->img.plane[2];
160 |
161 | memcpy(en->picture->img.plane[0], nv12_buf, nPicSize);
162 | for (i = 0; i < nPicSize / 4; i++) {
163 | *(u + i) = *(nv12_buf + nPicSize + i * 2);
164 | *(v + i) = *(nv12_buf + nPicSize + i * 2 + 1);
165 | }
166 |
167 |
168 | //1. the first step: encode NV12 into H264 NALUs.
169 | //this line is slow in nexus5.
170 | i_frame_size = x264_encoder_encode(
171 | en->handle,
172 | &(en->nal),
173 | &count_of_NALU,
174 | en->picture,
175 | &pic_out
176 | );
177 |
178 | if (i_frame_size < 0) {
179 | return -1;
180 | }
181 |
182 | /**
183 | * 2. The second step:
184 | * transfer several NALUs to RTMP server with foreach.
185 | * Two NAL types : SPS & PPS are very important.
186 | */
187 | for (i = 0; i < count_of_NALU; i++) {
188 | memcpy(pTemp, en->nal[i].p_payload, en->nal[i].i_payload);
189 |
190 | if (en->nal[i].i_type == NAL_SPS) {//this NAL type is SPS.
191 | sps_len = en->nal[i].i_payload - 4;
192 | memcpy(sps, en->nal[i].p_payload + 4, sps_len);
193 | } else if (en->nal[i].i_type == NAL_PPS) {//this NAL type is PPS.
194 | pps_len = en->nal[i].i_payload - 4;
195 | memcpy(pps, en->nal[i].p_payload + 4, pps_len);
196 | if (first == 0) {
197 | send_video_sps_pps(sps, sps_len, pps, pps_len);
198 | first = 1;
199 | }
200 | } else {
201 | send_rtmp_video(en->nal[i].p_payload,
202 | i_frame_size - result,
203 | getSystemTime());
204 | }
205 | pTemp += en->nal[i].i_payload;
206 | result += en->nal[i].i_payload;
207 |
208 | //release buffers.
209 | (*env)->ReleaseByteArrayElements(env, in, nv12_buf, 0);
210 | (*env)->ReleaseByteArrayElements(env, out, h264_buf, 0);
211 | }
212 | return result;
213 | }
214 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/parseurl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | #include "rtmp_sys.h"
31 | #include "log.h"
32 |
33 | int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port,
34 | AVal *playpath, AVal *app)
35 | {
36 | char *p, *end, *col, *ques, *slash;
37 |
38 | RTMP_Log(RTMP_LOGDEBUG, "Parsing...");
39 |
40 | *protocol = RTMP_PROTOCOL_RTMP;
41 | *port = 0;
42 | playpath->av_len = 0;
43 | playpath->av_val = NULL;
44 | app->av_len = 0;
45 | app->av_val = NULL;
46 |
47 | /* Old School Parsing */
48 |
49 | /* look for usual :// pattern */
50 | p = strstr(url, "://");
51 | if(!p) {
52 | RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!");
53 | return FALSE;
54 | }
55 | {
56 | int len = (int)(p-url);
57 |
58 | if(len == 4 && strncasecmp(url, "rtmp", 4)==0)
59 | *protocol = RTMP_PROTOCOL_RTMP;
60 | else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0)
61 | *protocol = RTMP_PROTOCOL_RTMPT;
62 | else if(len == 5 && strncasecmp(url, "rtmps", 5)==0)
63 | *protocol = RTMP_PROTOCOL_RTMPS;
64 | else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0)
65 | *protocol = RTMP_PROTOCOL_RTMPE;
66 | else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0)
67 | *protocol = RTMP_PROTOCOL_RTMFP;
68 | else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0)
69 | *protocol = RTMP_PROTOCOL_RTMPTE;
70 | else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0)
71 | *protocol = RTMP_PROTOCOL_RTMPTS;
72 | else {
73 | RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n");
74 | goto parsehost;
75 | }
76 | }
77 |
78 | RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol);
79 |
80 | parsehost:
81 | /* let's get the hostname */
82 | p+=3;
83 |
84 | /* check for sudden death */
85 | if(*p==0) {
86 | RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!");
87 | return FALSE;
88 | }
89 |
90 | end = p + strlen(p);
91 | col = strchr(p, ':');
92 | ques = strchr(p, '?');
93 | slash = strchr(p, '/');
94 |
95 | {
96 | int hostlen;
97 | if(slash)
98 | hostlen = slash - p;
99 | else
100 | hostlen = end - p;
101 | if(col && col -p < hostlen)
102 | hostlen = col - p;
103 |
104 | if(hostlen < 256) {
105 | host->av_val = p;
106 | host->av_len = hostlen;
107 | RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val);
108 | } else {
109 | RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!");
110 | }
111 |
112 | p+=hostlen;
113 | }
114 |
115 | /* get the port number if available */
116 | if(*p == ':') {
117 | unsigned int p2;
118 | p++;
119 | p2 = atoi(p);
120 | if(p2 > 65535) {
121 | RTMP_Log(RTMP_LOGWARNING, "Invalid port number!");
122 | } else {
123 | *port = p2;
124 | }
125 | }
126 |
127 | if(!slash) {
128 | RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!");
129 | return TRUE;
130 | }
131 | p = slash+1;
132 |
133 | {
134 | /* parse application
135 | *
136 | * rtmp://host[:port]/app[/appinstance][/...]
137 | * application = app[/appinstance]
138 | */
139 |
140 | char *slash2, *slash3 = NULL, *slash4 = NULL;
141 | int applen, appnamelen;
142 |
143 | slash2 = strchr(p, '/');
144 | if(slash2)
145 | slash3 = strchr(slash2+1, '/');
146 | if(slash3)
147 | slash4 = strchr(slash3+1, '/');
148 |
149 | applen = end-p; /* ondemand, pass all parameters as app */
150 | appnamelen = applen; /* ondemand length */
151 |
152 | if(ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */
153 | appnamelen = ques-p;
154 | }
155 | else if(strncmp(p, "ondemand/", 9)==0) {
156 | /* app = ondemand/foobar, only pass app=ondemand */
157 | applen = 8;
158 | appnamelen = 8;
159 | }
160 | else { /* app!=ondemand, so app is app[/appinstance] */
161 | if(slash4)
162 | appnamelen = slash4-p;
163 | else if(slash3)
164 | appnamelen = slash3-p;
165 | else if(slash2)
166 | appnamelen = slash2-p;
167 |
168 | applen = appnamelen;
169 | }
170 |
171 | app->av_val = p;
172 | app->av_len = applen;
173 | RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p);
174 |
175 | p += appnamelen;
176 | }
177 |
178 | if (*p == '/')
179 | p++;
180 |
181 | if (end-p) {
182 | AVal av = {p, end-p};
183 | RTMP_ParsePlaypath(&av, playpath);
184 | }
185 |
186 | return TRUE;
187 | }
188 |
189 | /*
190 | * Extracts playpath from RTMP URL. playpath is the file part of the
191 | * URL, i.e. the part that comes after rtmp://host:port/app/
192 | *
193 | * Returns the stream name in a format understood by FMS. The name is
194 | * the playpath part of the URL with formatting depending on the stream
195 | * type:
196 | *
197 | * mp4 streams: prepend "mp4:", remove extension
198 | * mp3 streams: prepend "mp3:", remove extension
199 | * flv streams: remove extension
200 | */
201 | void RTMP_ParsePlaypath(AVal *in, AVal *out) {
202 | int addMP4 = 0;
203 | int addMP3 = 0;
204 | int subExt = 0;
205 | const char *playpath = in->av_val;
206 | const char *temp, *q, *ext = NULL;
207 | const char *ppstart = playpath;
208 | char *streamname, *destptr, *p;
209 |
210 | int pplen = in->av_len;
211 |
212 | out->av_val = NULL;
213 | out->av_len = 0;
214 |
215 | if ((*ppstart == '?') &&
216 | (temp=strstr(ppstart, "slist=")) != 0) {
217 | ppstart = temp+6;
218 | pplen = strlen(ppstart);
219 |
220 | temp = strchr(ppstart, '&');
221 | if (temp) {
222 | pplen = temp-ppstart;
223 | }
224 | }
225 |
226 | q = strchr(ppstart, '?');
227 | if (pplen >= 4) {
228 | if (q)
229 | ext = q-4;
230 | else
231 | ext = &ppstart[pplen-4];
232 | if ((strncmp(ext, ".f4v", 4) == 0) ||
233 | (strncmp(ext, ".mp4", 4) == 0)) {
234 | addMP4 = 1;
235 | subExt = 1;
236 | /* Only remove .flv from rtmp URL, not slist params */
237 | } else if ((ppstart == playpath) &&
238 | (strncmp(ext, ".flv", 4) == 0)) {
239 | subExt = 1;
240 | } else if (strncmp(ext, ".mp3", 4) == 0) {
241 | addMP3 = 1;
242 | subExt = 1;
243 | }
244 | }
245 |
246 | streamname = (char *)malloc((pplen+4+1)*sizeof(char));
247 | if (!streamname)
248 | return;
249 |
250 | destptr = streamname;
251 | if (addMP4) {
252 | if (strncmp(ppstart, "mp4:", 4)) {
253 | strcpy(destptr, "mp4:");
254 | destptr += 4;
255 | } else {
256 | subExt = 0;
257 | }
258 | } else if (addMP3) {
259 | if (strncmp(ppstart, "mp3:", 4)) {
260 | strcpy(destptr, "mp3:");
261 | destptr += 4;
262 | } else {
263 | subExt = 0;
264 | }
265 | }
266 |
267 | for (p=(char *)ppstart; pplen >0;) {
268 | /* skip extension */
269 | if (subExt && p == ext) {
270 | p += 4;
271 | pplen -= 4;
272 | continue;
273 | }
274 | if (*p == '%') {
275 | unsigned int c;
276 | sscanf(p+1, "%02x", &c);
277 | *destptr++ = c;
278 | pplen -= 3;
279 | p += 3;
280 | } else {
281 | *destptr++ = *p++;
282 | pplen--;
283 | }
284 | }
285 | *destptr = '\0';
286 |
287 | out->av_val = streamname;
288 | out->av_len = destptr - streamname;
289 | }
290 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/parseurl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 Andrej Stepanchuk
3 | * Copyright (C) 2009-2010 Howard Chu
4 | *
5 | * This file is part of librtmp.
6 | *
7 | * librtmp is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU Lesser General Public License as
9 | * published by the Free Software Foundation; either version 2.1,
10 | * or (at your option) any later version.
11 | *
12 | * librtmp is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with librtmp see the file COPYING. If not, write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 | * Boston, MA 02110-1301, USA.
21 | * http://www.gnu.org/copyleft/lgpl.html
22 | */
23 |
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | #include "rtmp_sys.h"
31 | #include "log.h"
32 |
33 | int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port,
34 | AVal *playpath, AVal *app)
35 | {
36 | char *p, *end, *col, *ques, *slash;
37 |
38 | RTMP_Log(RTMP_LOGDEBUG, "Parsing...");
39 |
40 | *protocol = RTMP_PROTOCOL_RTMP;
41 | *port = 0;
42 | playpath->av_len = 0;
43 | playpath->av_val = NULL;
44 | app->av_len = 0;
45 | app->av_val = NULL;
46 |
47 | /* Old School Parsing */
48 |
49 | /* look for usual :// pattern */
50 | p = strstr(url, "://");
51 | if(!p) {
52 | RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!");
53 | return FALSE;
54 | }
55 | {
56 | int len = (int)(p-url);
57 |
58 | if(len == 4 && strncasecmp(url, "rtmp", 4)==0)
59 | *protocol = RTMP_PROTOCOL_RTMP;
60 | else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0)
61 | *protocol = RTMP_PROTOCOL_RTMPT;
62 | else if(len == 5 && strncasecmp(url, "rtmps", 5)==0)
63 | *protocol = RTMP_PROTOCOL_RTMPS;
64 | else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0)
65 | *protocol = RTMP_PROTOCOL_RTMPE;
66 | else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0)
67 | *protocol = RTMP_PROTOCOL_RTMFP;
68 | else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0)
69 | *protocol = RTMP_PROTOCOL_RTMPTE;
70 | else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0)
71 | *protocol = RTMP_PROTOCOL_RTMPTS;
72 | else {
73 | RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n");
74 | goto parsehost;
75 | }
76 | }
77 |
78 | RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol);
79 |
80 | parsehost:
81 | /* let's get the hostname */
82 | p+=3;
83 |
84 | /* check for sudden death */
85 | if(*p==0) {
86 | RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!");
87 | return FALSE;
88 | }
89 |
90 | end = p + strlen(p);
91 | col = strchr(p, ':');
92 | ques = strchr(p, '?');
93 | slash = strchr(p, '/');
94 |
95 | {
96 | int hostlen;
97 | if(slash)
98 | hostlen = slash - p;
99 | else
100 | hostlen = end - p;
101 | if(col && col -p < hostlen)
102 | hostlen = col - p;
103 |
104 | if(hostlen < 256) {
105 | host->av_val = p;
106 | host->av_len = hostlen;
107 | RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val);
108 | } else {
109 | RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!");
110 | }
111 |
112 | p+=hostlen;
113 | }
114 |
115 | /* get the port number if available */
116 | if(*p == ':') {
117 | unsigned int p2;
118 | p++;
119 | p2 = atoi(p);
120 | if(p2 > 65535) {
121 | RTMP_Log(RTMP_LOGWARNING, "Invalid port number!");
122 | } else {
123 | *port = p2;
124 | }
125 | }
126 |
127 | if(!slash) {
128 | RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!");
129 | return TRUE;
130 | }
131 | p = slash+1;
132 |
133 | {
134 | /* parse application
135 | *
136 | * rtmp://host[:port]/app[/appinstance][/...]
137 | * application = app[/appinstance]
138 | */
139 |
140 | char *slash2, *slash3 = NULL, *slash4 = NULL;
141 | int applen, appnamelen;
142 |
143 | slash2 = strchr(p, '/');
144 | if(slash2)
145 | slash3 = strchr(slash2+1, '/');
146 | if(slash3)
147 | slash4 = strchr(slash3+1, '/');
148 |
149 | applen = end-p; /* ondemand, pass all parameters as app */
150 | appnamelen = applen; /* ondemand length */
151 |
152 | if(ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */
153 | appnamelen = ques-p;
154 | }
155 | else if(strncmp(p, "ondemand/", 9)==0) {
156 | /* app = ondemand/foobar, only pass app=ondemand */
157 | applen = 8;
158 | appnamelen = 8;
159 | }
160 | else { /* app!=ondemand, so app is app[/appinstance] */
161 | if(slash4)
162 | appnamelen = slash4-p;
163 | else if(slash3)
164 | appnamelen = slash3-p;
165 | else if(slash2)
166 | appnamelen = slash2-p;
167 |
168 | applen = appnamelen;
169 | }
170 |
171 | app->av_val = p;
172 | app->av_len = applen;
173 | RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p);
174 |
175 | p += appnamelen;
176 | }
177 |
178 | if (*p == '/')
179 | p++;
180 |
181 | if (end-p) {
182 | AVal av = {p, end-p};
183 | RTMP_ParsePlaypath(&av, playpath);
184 | }
185 |
186 | return TRUE;
187 | }
188 |
189 | /*
190 | * Extracts playpath from RTMP URL. playpath is the file part of the
191 | * URL, i.e. the part that comes after rtmp://host:port/app/
192 | *
193 | * Returns the stream name in a format understood by FMS. The name is
194 | * the playpath part of the URL with formatting depending on the stream
195 | * type:
196 | *
197 | * mp4 streams: prepend "mp4:", remove extension
198 | * mp3 streams: prepend "mp3:", remove extension
199 | * flv streams: remove extension
200 | */
201 | void RTMP_ParsePlaypath(AVal *in, AVal *out) {
202 | int addMP4 = 0;
203 | int addMP3 = 0;
204 | int subExt = 0;
205 | const char *playpath = in->av_val;
206 | const char *temp, *q, *ext = NULL;
207 | const char *ppstart = playpath;
208 | char *streamname, *destptr, *p;
209 |
210 | int pplen = in->av_len;
211 |
212 | out->av_val = NULL;
213 | out->av_len = 0;
214 |
215 | if ((*ppstart == '?') &&
216 | (temp=strstr(ppstart, "slist=")) != 0) {
217 | ppstart = temp+6;
218 | pplen = strlen(ppstart);
219 |
220 | temp = strchr(ppstart, '&');
221 | if (temp) {
222 | pplen = temp-ppstart;
223 | }
224 | }
225 |
226 | q = strchr(ppstart, '?');
227 | if (pplen >= 4) {
228 | if (q)
229 | ext = q-4;
230 | else
231 | ext = &ppstart[pplen-4];
232 | if ((strncmp(ext, ".f4v", 4) == 0) ||
233 | (strncmp(ext, ".mp4", 4) == 0)) {
234 | addMP4 = 1;
235 | subExt = 1;
236 | /* Only remove .flv from rtmp URL, not slist params */
237 | } else if ((ppstart == playpath) &&
238 | (strncmp(ext, ".flv", 4) == 0)) {
239 | subExt = 1;
240 | } else if (strncmp(ext, ".mp3", 4) == 0) {
241 | addMP3 = 1;
242 | subExt = 1;
243 | }
244 | }
245 |
246 | streamname = (char *)malloc((pplen+4+1)*sizeof(char));
247 | if (!streamname)
248 | return;
249 |
250 | destptr = streamname;
251 | if (addMP4) {
252 | if (strncmp(ppstart, "mp4:", 4)) {
253 | strcpy(destptr, "mp4:");
254 | destptr += 4;
255 | } else {
256 | subExt = 0;
257 | }
258 | } else if (addMP3) {
259 | if (strncmp(ppstart, "mp3:", 4)) {
260 | strcpy(destptr, "mp3:");
261 | destptr += 4;
262 | } else {
263 | subExt = 0;
264 | }
265 | }
266 |
267 | for (p=(char *)ppstart; pplen >0;) {
268 | /* skip extension */
269 | if (subExt && p == ext) {
270 | p += 4;
271 | pplen -= 4;
272 | continue;
273 | }
274 | if (*p == '%') {
275 | unsigned int c;
276 | sscanf(p+1, "%02x", &c);
277 | *destptr++ = c;
278 | pplen -= 3;
279 | p += 3;
280 | } else {
281 | *destptr++ = *p++;
282 | pplen--;
283 | }
284 | }
285 | *destptr = '\0';
286 |
287 | out->av_val = streamname;
288 | out->av_len = destptr - streamname;
289 | }
290 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/librtmp/librtmp.3:
--------------------------------------------------------------------------------
1 | .TH LIBRTMP 3 "2011-07-20" "RTMPDump v2.4"
2 | .\" Copyright 2011 Howard Chu.
3 | .\" Copying permitted according to the GNU General Public License V2.
4 | .SH NAME
5 | librtmp \- RTMPDump Real-Time Messaging Protocol API
6 | .SH LIBRARY
7 | RTMPDump RTMP (librtmp, -lrtmp)
8 | .SH SYNOPSIS
9 | .B #include
10 | .SH DESCRIPTION
11 | The Real-Time Messaging Protocol (RTMP) is used for streaming
12 | multimedia content across a TCP/IP network. This API provides most client
13 | functions and a few server functions needed to support RTMP, RTMP tunneled
14 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and
15 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic
16 | RTMP specification has been published by Adobe but this API was
17 | reverse-engineered without use of the Adobe specification. As such, it may
18 | deviate from any published specifications but it usually duplicates the
19 | actual behavior of the original Adobe clients.
20 |
21 | The RTMPDump software package includes a basic client utility program
22 | in
23 | .BR rtmpdump (1),
24 | some sample servers, and a library used to provide programmatic access
25 | to the RTMP protocol. This man page gives an overview of the RTMP
26 | library routines. These routines are found in the -lrtmp library. Many
27 | other routines are also available, but they are not documented yet.
28 |
29 | The basic interaction is as follows. A session handle is created using
30 | .BR RTMP_Alloc ()
31 | and initialized using
32 | .BR RTMP_Init ().
33 | All session parameters are provided using
34 | .BR RTMP_SetupURL ().
35 | The network connection is established using
36 | .BR RTMP_Connect (),
37 | and then the RTMP session is established using
38 | .BR RTMP_ConnectStream ().
39 | The stream is read using
40 | .BR RTMP_Read ().
41 | A client can publish a stream by calling
42 | .BR RTMP_EnableWrite ()
43 | before the
44 | .BR RTMP_Connect ()
45 | call, and then using
46 | .BR RTMP_Write ()
47 | after the session is established.
48 | While a stream is playing it may be paused and unpaused using
49 | .BR RTMP_Pause ().
50 | The stream playback position can be moved using
51 | .BR RTMP_Seek ().
52 | When
53 | .BR RTMP_Read ()
54 | returns 0 bytes, the stream is complete and may be closed using
55 | .BR RTMP_Close ().
56 | The session handle is freed using
57 | .BR RTMP_Free ().
58 |
59 | All data is transferred using FLV format. The basic session requires
60 | an RTMP URL. The RTMP URL format is of the form
61 | .nf
62 | rtmp[t][e|s]://hostname[:port][/app[/playpath]]
63 | .fi
64 |
65 | Plain rtmp, as well as tunneled and encrypted sessions are supported.
66 |
67 | Additional options may be specified by appending space-separated
68 | key=value pairs to the URL. Special characters in values may need
69 | to be escaped to prevent misinterpretation by the option parser.
70 | The escape encoding uses a backslash followed by two hexadecimal digits
71 | representing the ASCII value of the character. E.g., spaces must
72 | be escaped as \fB\\20\fP and backslashes must be escaped as \fB\\5c\fP.
73 | .SH OPTIONS
74 | .SS "Network Parameters"
75 | These options define how to connect to the media server.
76 | .TP
77 | .BI socks= host:port
78 | Use the specified SOCKS4 proxy.
79 | .SS "Connection Parameters"
80 | These options define the content of the RTMP Connect request packet.
81 | If correct values are not provided, the media server will reject the
82 | connection attempt.
83 | .TP
84 | .BI app= name
85 | Name of application to connect to on the RTMP server. Overrides
86 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot
87 | determine the app name automatically, so it must be given explicitly
88 | using this option.
89 | .TP
90 | .BI tcUrl= url
91 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app.
92 | .TP
93 | .BI pageUrl= url
94 | URL of the web page in which the media was embedded. By default no
95 | value will be sent.
96 | .TP
97 | .BI swfUrl= url
98 | URL of the SWF player for the media. By default no value will be sent.
99 | .TP
100 | .BI flashVer= version
101 | Version of the Flash plugin used to run the SWF player. The
102 | default is "LNX 10,0,32,18".
103 | .TP
104 | .BI conn= type:data
105 | Append arbitrary AMF data to the Connect message. The type
106 | must be B for Boolean, N for number, S for string, O for object, or Z
107 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE,
108 | respectively. Likewise for Objects the data must be 0 or 1 to end or
109 | begin an object, respectively. Data items in subobjects may be named, by
110 | prefixing the type with 'N' and specifying the name before the value, e.g.
111 | NB:myFlag:1. This option may be used multiple times to construct arbitrary
112 | AMF sequences. E.g.
113 | .nf
114 | conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0
115 | .fi
116 | .SS "Session Parameters"
117 | These options take effect after the Connect request has succeeded.
118 | .TP
119 | .BI playpath= path
120 | Overrides the playpath parsed from the RTMP URL. Sometimes the
121 | rtmpdump URL parser cannot determine the correct playpath
122 | automatically, so it must be given explicitly using this option.
123 | .TP
124 | .BI playlist= 0|1
125 | If the value is 1 or TRUE, issue a set_playlist command before sending the
126 | play command. The playlist will just contain the current playpath. If the
127 | value is 0 or FALSE, the set_playlist command will not be sent. The
128 | default is FALSE.
129 | .TP
130 | .BI live= 0|1
131 | Specify that the media is a live stream. No resuming or seeking in
132 | live streams is possible.
133 | .TP
134 | .BI subscribe= path
135 | Name of live stream to subscribe to. Defaults to
136 | .IR playpath .
137 | .TP
138 | .BI start= num
139 | Start at
140 | .I num
141 | seconds into the stream. Not valid for live streams.
142 | .TP
143 | .BI stop= num
144 | Stop at
145 | .I num
146 | seconds into the stream.
147 | .TP
148 | .BI buffer= num
149 | Set buffer time to
150 | .I num
151 | milliseconds. The default is 30000.
152 | .TP
153 | .BI timeout= num
154 | Timeout the session after
155 | .I num
156 | seconds without receiving any data from the server. The default is 120.
157 | .SS "Security Parameters"
158 | These options handle additional authentication requests from the server.
159 | .TP
160 | .BI token= key
161 | Key for SecureToken response, used if the server requires SecureToken
162 | authentication.
163 | .TP
164 | .BI jtv= JSON
165 | JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken
166 | .TP
167 | .BI swfVfy= 0|1
168 | If the value is 1 or TRUE, the SWF player is retrieved from the
169 | specified
170 | .I swfUrl
171 | for performing SWF Verification. The SWF hash and size (used in the
172 | verification step) are computed automatically. Also the SWF information is
173 | cached in a
174 | .I .swfinfo
175 | file in the user's home directory, so that it doesn't need to be retrieved
176 | and recalculated every time. The .swfinfo file records
177 | the SWF URL, the time it was fetched, the modification timestamp of the SWF
178 | file, its size, and its hash. By default, the cached info will be used
179 | for 30 days before re-checking.
180 | .TP
181 | .BI swfAge= days
182 | Specify how many days to use the cached SWF info before re-checking. Use
183 | 0 to always check the SWF URL. Note that if the check shows that the
184 | SWF file has the same modification timestamp as before, it will not be
185 | retrieved again.
186 | .SH EXAMPLES
187 | An example character string suitable for use with
188 | .BR RTMP_SetupURL ():
189 | .nf
190 | "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1"
191 | .fi
192 | .SH ENVIRONMENT
193 | .TP
194 | .B HOME
195 | The value of
196 | .RB $ HOME
197 | is used as the location for the
198 | .I .swfinfo
199 | file.
200 | .SH FILES
201 | .TP
202 | .I $HOME/.swfinfo
203 | Cache of SWF Verification information
204 | .SH "SEE ALSO"
205 | .BR rtmpdump (1),
206 | .BR rtmpgw (8)
207 | .SH AUTHORS
208 | Andrej Stepanchuk, Howard Chu, The Flvstreamer Team
209 | .br
210 |
211 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/librtmp/librtmp.3:
--------------------------------------------------------------------------------
1 | .TH LIBRTMP 3 "2011-07-20" "RTMPDump v2.4"
2 | .\" Copyright 2011 Howard Chu.
3 | .\" Copying permitted according to the GNU General Public License V2.
4 | .SH NAME
5 | librtmp \- RTMPDump Real-Time Messaging Protocol API
6 | .SH LIBRARY
7 | RTMPDump RTMP (librtmp, -lrtmp)
8 | .SH SYNOPSIS
9 | .B #include
10 | .SH DESCRIPTION
11 | The Real-Time Messaging Protocol (RTMP) is used for streaming
12 | multimedia content across a TCP/IP network. This API provides most client
13 | functions and a few server functions needed to support RTMP, RTMP tunneled
14 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and
15 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic
16 | RTMP specification has been published by Adobe but this API was
17 | reverse-engineered without use of the Adobe specification. As such, it may
18 | deviate from any published specifications but it usually duplicates the
19 | actual behavior of the original Adobe clients.
20 |
21 | The RTMPDump software package includes a basic client utility program
22 | in
23 | .BR rtmpdump (1),
24 | some sample servers, and a library used to provide programmatic access
25 | to the RTMP protocol. This man page gives an overview of the RTMP
26 | library routines. These routines are found in the -lrtmp library. Many
27 | other routines are also available, but they are not documented yet.
28 |
29 | The basic interaction is as follows. A session handle is created using
30 | .BR RTMP_Alloc ()
31 | and initialized using
32 | .BR RTMP_Init ().
33 | All session parameters are provided using
34 | .BR RTMP_SetupURL ().
35 | The network connection is established using
36 | .BR RTMP_Connect (),
37 | and then the RTMP session is established using
38 | .BR RTMP_ConnectStream ().
39 | The stream is read using
40 | .BR RTMP_Read ().
41 | A client can publish a stream by calling
42 | .BR RTMP_EnableWrite ()
43 | before the
44 | .BR RTMP_Connect ()
45 | call, and then using
46 | .BR RTMP_Write ()
47 | after the session is established.
48 | While a stream is playing it may be paused and unpaused using
49 | .BR RTMP_Pause ().
50 | The stream playback position can be moved using
51 | .BR RTMP_Seek ().
52 | When
53 | .BR RTMP_Read ()
54 | returns 0 bytes, the stream is complete and may be closed using
55 | .BR RTMP_Close ().
56 | The session handle is freed using
57 | .BR RTMP_Free ().
58 |
59 | All data is transferred using FLV format. The basic session requires
60 | an RTMP URL. The RTMP URL format is of the form
61 | .nf
62 | rtmp[t][e|s]://hostname[:port][/app[/playpath]]
63 | .fi
64 |
65 | Plain rtmp, as well as tunneled and encrypted sessions are supported.
66 |
67 | Additional options may be specified by appending space-separated
68 | key=value pairs to the URL. Special characters in values may need
69 | to be escaped to prevent misinterpretation by the option parser.
70 | The escape encoding uses a backslash followed by two hexadecimal digits
71 | representing the ASCII value of the character. E.g., spaces must
72 | be escaped as \fB\\20\fP and backslashes must be escaped as \fB\\5c\fP.
73 | .SH OPTIONS
74 | .SS "Network Parameters"
75 | These options define how to connect to the media server.
76 | .TP
77 | .BI socks= host:port
78 | Use the specified SOCKS4 proxy.
79 | .SS "Connection Parameters"
80 | These options define the content of the RTMP Connect request packet.
81 | If correct values are not provided, the media server will reject the
82 | connection attempt.
83 | .TP
84 | .BI app= name
85 | Name of application to connect to on the RTMP server. Overrides
86 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot
87 | determine the app name automatically, so it must be given explicitly
88 | using this option.
89 | .TP
90 | .BI tcUrl= url
91 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app.
92 | .TP
93 | .BI pageUrl= url
94 | URL of the web page in which the media was embedded. By default no
95 | value will be sent.
96 | .TP
97 | .BI swfUrl= url
98 | URL of the SWF player for the media. By default no value will be sent.
99 | .TP
100 | .BI flashVer= version
101 | Version of the Flash plugin used to run the SWF player. The
102 | default is "LNX 10,0,32,18".
103 | .TP
104 | .BI conn= type:data
105 | Append arbitrary AMF data to the Connect message. The type
106 | must be B for Boolean, N for number, S for string, O for object, or Z
107 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE,
108 | respectively. Likewise for Objects the data must be 0 or 1 to end or
109 | begin an object, respectively. Data items in subobjects may be named, by
110 | prefixing the type with 'N' and specifying the name before the value, e.g.
111 | NB:myFlag:1. This option may be used multiple times to construct arbitrary
112 | AMF sequences. E.g.
113 | .nf
114 | conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0
115 | .fi
116 | .SS "Session Parameters"
117 | These options take effect after the Connect request has succeeded.
118 | .TP
119 | .BI playpath= path
120 | Overrides the playpath parsed from the RTMP URL. Sometimes the
121 | rtmpdump URL parser cannot determine the correct playpath
122 | automatically, so it must be given explicitly using this option.
123 | .TP
124 | .BI playlist= 0|1
125 | If the value is 1 or TRUE, issue a set_playlist command before sending the
126 | play command. The playlist will just contain the current playpath. If the
127 | value is 0 or FALSE, the set_playlist command will not be sent. The
128 | default is FALSE.
129 | .TP
130 | .BI live= 0|1
131 | Specify that the media is a live stream. No resuming or seeking in
132 | live streams is possible.
133 | .TP
134 | .BI subscribe= path
135 | Name of live stream to subscribe to. Defaults to
136 | .IR playpath .
137 | .TP
138 | .BI start= num
139 | Start at
140 | .I num
141 | seconds into the stream. Not valid for live streams.
142 | .TP
143 | .BI stop= num
144 | Stop at
145 | .I num
146 | seconds into the stream.
147 | .TP
148 | .BI buffer= num
149 | Set buffer time to
150 | .I num
151 | milliseconds. The default is 30000.
152 | .TP
153 | .BI timeout= num
154 | Timeout the session after
155 | .I num
156 | seconds without receiving any data from the server. The default is 120.
157 | .SS "Security Parameters"
158 | These options handle additional authentication requests from the server.
159 | .TP
160 | .BI token= key
161 | Key for SecureToken response, used if the server requires SecureToken
162 | authentication.
163 | .TP
164 | .BI jtv= JSON
165 | JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken
166 | .TP
167 | .BI swfVfy= 0|1
168 | If the value is 1 or TRUE, the SWF player is retrieved from the
169 | specified
170 | .I swfUrl
171 | for performing SWF Verification. The SWF hash and size (used in the
172 | verification step) are computed automatically. Also the SWF information is
173 | cached in a
174 | .I .swfinfo
175 | file in the user's home directory, so that it doesn't need to be retrieved
176 | and recalculated every time. The .swfinfo file records
177 | the SWF URL, the time it was fetched, the modification timestamp of the SWF
178 | file, its size, and its hash. By default, the cached info will be used
179 | for 30 days before re-checking.
180 | .TP
181 | .BI swfAge= days
182 | Specify how many days to use the cached SWF info before re-checking. Use
183 | 0 to always check the SWF URL. Note that if the check shows that the
184 | SWF file has the same modification timestamp as before, it will not be
185 | retrieved again.
186 | .SH EXAMPLES
187 | An example character string suitable for use with
188 | .BR RTMP_SetupURL ():
189 | .nf
190 | "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1"
191 | .fi
192 | .SH ENVIRONMENT
193 | .TP
194 | .B HOME
195 | The value of
196 | .RB $ HOME
197 | is used as the location for the
198 | .I .swfinfo
199 | file.
200 | .SH FILES
201 | .TP
202 | .I $HOME/.swfinfo
203 | Cache of SWF Verification information
204 | .SH "SEE ALSO"
205 | .BR rtmpdump (1),
206 | .BR rtmpgw (8)
207 | .SH AUTHORS
208 | Andrej Stepanchuk, Howard Chu, The Flvstreamer Team
209 | .br
210 |
211 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/softcodec/xiecc_rtmp.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "../librtmp/rtmp.h"
5 | #include
6 | #include "../libx264/include/x264.h"
7 | #include "xiecc_rtmp.h"
8 | #include
9 |
10 | #define RTMP_HEAD_SIZE (sizeof(RTMPPacket)+RTMP_MAX_HEADER_SIZE)
11 |
12 | #define LOG_TAG "rtmp-muxer"
13 |
14 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
15 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
16 |
17 | RTMP *rtmp;
18 | int StartTime;
19 | int rtmp_open_for_write(const char * url) {
20 | rtmp = RTMP_Alloc();
21 | if (rtmp == NULL) {
22 | return -1;
23 | }
24 |
25 | RTMP_Init(rtmp);
26 | int ret = RTMP_SetupURL(rtmp, url);
27 |
28 | if (!ret) {
29 | RTMP_Free(rtmp);
30 | return -2;
31 | }
32 |
33 | RTMP_EnableWrite(rtmp);
34 |
35 | ret = RTMP_Connect(rtmp, NULL);
36 | if (!ret) {
37 | RTMP_Free(rtmp);
38 | return -3;
39 | }
40 | ret = RTMP_ConnectStream(rtmp, 0);
41 |
42 | if (!ret) {
43 | return -4;
44 | }
45 |
46 | StartTime=getSystemTime();
47 |
48 | return 1;
49 | }
50 | void send_video_sps_pps(uint8_t *sps, int sps_len, uint8_t *pps, int pps_len) {
51 | RTMPPacket * packet;
52 | unsigned char * body;
53 | int i;
54 | if (rtmp != NULL) {
55 | packet = (RTMPPacket *) malloc(RTMP_HEAD_SIZE + 1024);
56 | memset(packet, 0, RTMP_HEAD_SIZE);
57 |
58 | packet->m_body = (char *) packet + RTMP_HEAD_SIZE;
59 | body = (unsigned char *) packet->m_body;
60 | i = 0;
61 | body[i++] = 0x17;
62 | body[i++] = 0x00;
63 |
64 | body[i++] = 0x00;
65 | body[i++] = 0x00;
66 | body[i++] = 0x00;
67 |
68 | /*AVCDecoderConfigurationRecord*/
69 | body[i++] = 0x01;
70 | body[i++] = sps[1];
71 | body[i++] = sps[2];
72 | body[i++] = sps[3];
73 | body[i++] = 0xff;
74 |
75 | /*sps*/
76 | body[i++] = 0xe1;
77 | body[i++] = (sps_len >> 8) & 0xff;
78 | body[i++] = sps_len & 0xff;
79 | memcpy(&body[i], sps, sps_len);
80 |
81 | i += sps_len;
82 |
83 | /*pps*/
84 | body[i++] = 0x01;
85 | body[i++] = (pps_len >> 8) & 0xff;
86 | body[i++] = (pps_len) & 0xff;
87 | memcpy(&body[i], pps, pps_len);
88 | i += pps_len;
89 |
90 | packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
91 | packet->m_nBodySize = i;
92 | packet->m_nChannel = 0x04;
93 |
94 | packet->m_nTimeStamp = 0;
95 | packet->m_hasAbsTimestamp = 0;
96 | packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
97 | packet->m_nInfoField2 = rtmp->m_stream_id;
98 |
99 | if (RTMP_IsConnected(rtmp)) {
100 | //调用发送接口
101 | int success = RTMP_SendPacket(rtmp, packet, TRUE);
102 | if (success != 1) {
103 | LOGE("send_video_sps_pps fail");
104 | }
105 | } else {
106 | LOGE("send_video_sps_pps RTMP is not ready");
107 | }
108 | free(packet);
109 | }
110 | }
111 | void send_rtmp_video(uint8_t *data, int data_len, int timestamp) {
112 | int type;
113 | RTMPPacket * packet;
114 | unsigned char * body;
115 | unsigned char* buffer = data;
116 | uint32_t length = data_len;
117 |
118 | if (rtmp != NULL) {
119 | timestamp = timestamp - StartTime;
120 | /*去掉帧界定符(这里可能2种,但是sps or pps只能为 00 00 00 01)*/
121 | if (buffer[2] == 0x00) { /*00 00 00 01*/
122 | buffer += 4;
123 | length -= 4;
124 | } else if (buffer[2] == 0x01) { /*00 00 01*/
125 | buffer += 3;
126 | length -= 3;
127 | }
128 | type = buffer[0] & 0x1f;
129 |
130 | packet = (RTMPPacket *) malloc(RTMP_HEAD_SIZE + length + 9);
131 | memset(packet, 0, RTMP_HEAD_SIZE);
132 |
133 | packet->m_body = (char *) packet + RTMP_HEAD_SIZE;
134 | packet->m_nBodySize = length + 9;
135 |
136 | /*send video packet*/
137 | body = (unsigned char *) packet->m_body;
138 | memset(body, 0, length + 9);
139 |
140 | /*key frame*/
141 | body[0] = 0x27;
142 | if (type == NAL_SLICE_IDR) //此为关键帧
143 | {
144 | body[0] = 0x17;
145 | }
146 |
147 | body[1] = 0x01; /*nal unit*/
148 | body[2] = 0x00;
149 | body[3] = 0x00;
150 | body[4] = 0x00;
151 |
152 | body[5] = (length >> 24) & 0xff;
153 | body[6] = (length >> 16) & 0xff;
154 | body[7] = (length >> 8) & 0xff;
155 | body[8] = (length) & 0xff;
156 |
157 | /*copy data*/
158 | memcpy(&body[9], buffer, length);
159 |
160 | packet->m_nTimeStamp = timestamp;
161 | packet->m_hasAbsTimestamp = 0;
162 | packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
163 | packet->m_nInfoField2 = rtmp->m_stream_id;
164 | packet->m_nChannel = 0x04;
165 | packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
166 |
167 | if (RTMP_IsConnected(rtmp)) {
168 | // 调用发送接口
169 |
170 | int success = RTMP_SendPacket(rtmp, packet, TRUE);
171 | if (success != 1) {
172 | LOGE("send_rtmp_video fail");
173 | } else {
174 | // LOGE("發送成功");
175 | }
176 | } else {
177 | // rtmp_open_for_write();
178 | LOGE("send_rtmp_video RTMP is not ready");
179 | }
180 | free(packet);
181 | }
182 | }
183 |
184 | int isConnected()
185 | {
186 | if(rtmp!=NULL && RTMP_IsConnected(rtmp))
187 | return 1;
188 | else
189 | return 0;
190 | }
191 |
192 | void send_rtmp_audio_spec(unsigned char *spec_buf, uint32_t spec_len) {
193 |
194 |
195 | if (rtmp != NULL) {
196 | RTMPPacket * packet;
197 |
198 | unsigned char * body;
199 | uint32_t len;
200 |
201 | len = spec_len; /*spec data长度,一般是2*/
202 |
203 | packet = (RTMPPacket *)malloc(RTMP_HEAD_SIZE+len+2);
204 | memset(packet,0,RTMP_HEAD_SIZE);
205 |
206 | packet->m_body = (char *)packet + RTMP_HEAD_SIZE;
207 | body = (unsigned char *)packet->m_body;
208 |
209 | /*AF 00 + AAC RAW data*/
210 | body[0] = 0xAF;
211 | body[1] = 0x00;
212 | memcpy(&body[2],spec_buf,len); /*spec_buf是AAC sequence header数据*/
213 |
214 | packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
215 | packet->m_nBodySize = len + 2;
216 | packet->m_nChannel = 0x05;
217 | packet->m_nTimeStamp = 0;
218 | packet->m_hasAbsTimestamp = 0;
219 | packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
220 | packet->m_nInfoField2 = rtmp->m_stream_id;
221 |
222 | if (RTMP_IsConnected(rtmp)) {
223 | /*调用发送接口*/
224 | int success = RTMP_SendPacket(rtmp, packet, TRUE);
225 | if (success != 1) {
226 | LOGE("send_rtmp_audio_spec fail");
227 | }
228 | }
229 | // free(packet);
230 | } else {
231 | LOGE("send_rtmp_audio_spec RTMP is not ready");
232 | }
233 | }
234 |
235 | void send_rtmp_audio(unsigned char *buf, uint32_t len,int time) {
236 |
237 | unsigned char* buffer = buf;
238 | uint32_t length = len;
239 | time=time-StartTime;
240 | if(rtmp != NULL)
241 | {
242 | buffer += 7;
243 | length -= 7;
244 | if (length > 0) {
245 | RTMPPacket * packet;
246 | unsigned char * body;
247 |
248 | packet = (RTMPPacket *)malloc(RTMP_HEAD_SIZE + length + 2);
249 | memset(packet,0,RTMP_HEAD_SIZE);
250 |
251 | packet->m_body = (char *)packet + RTMP_HEAD_SIZE;
252 | body = (unsigned char *)packet->m_body;
253 |
254 | /*AF 01 + AAC RAW data*/
255 | body[0] = 0xAF;
256 | body[1] = 0x01;
257 | memcpy(&body[2],buffer,length);
258 |
259 | packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
260 | packet->m_nBodySize = length + 2;
261 | packet->m_nChannel = 0x05;
262 | packet->m_nTimeStamp = time;
263 | packet->m_hasAbsTimestamp = 0;
264 | packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
265 | packet->m_nInfoField2 = rtmp->m_stream_id;
266 |
267 | if(RTMP_IsConnected(rtmp))
268 | {
269 | /*调用发送接口*/
270 | int success = RTMP_SendPacket(rtmp,packet,TRUE);
271 | if(success != 1)
272 | {
273 | LOGE("send_rtmp_audio fail");
274 | }
275 | }
276 | free(packet);
277 | }
278 | }
279 | else
280 | {
281 | LOGE("send_rtmp_audio RTMP is not ready");
282 | }
283 |
284 | }
285 |
286 | int stopRtmpConnect() {
287 | if (isConnected()) {
288 |
289 | //時間戳要歸0 否則打次傳輸 會有問題
290 | // videotimeoffset=0;
291 | // audiotimeoffset=0;
292 |
293 | RTMP_Close(rtmp);
294 | RTMP_Free(rtmp);
295 | rtmp = NULL;
296 | return 1;
297 | }
298 | return -1;
299 | }
300 |
--------------------------------------------------------------------------------
/x264-codec/src/main/jni/libopenh264/include/wels/codec_def.h:
--------------------------------------------------------------------------------
1 | /*!
2 | * \copy
3 | * Copyright (c) 2013, Cisco Systems
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | *
13 | * * Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | * POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | */
32 |
33 | #ifndef WELS_VIDEO_CODEC_DEFINITION_H__
34 | #define WELS_VIDEO_CODEC_DEFINITION_H__
35 |
36 | /**
37 | * @file codec_def.h
38 | */
39 |
40 | /**
41 | * @brief Enumerate the type of video format
42 | */
43 | typedef enum {
44 | videoFormatRGB = 1, ///< rgb color formats
45 | videoFormatRGBA = 2,
46 | videoFormatRGB555 = 3,
47 | videoFormatRGB565 = 4,
48 | videoFormatBGR = 5,
49 | videoFormatBGRA = 6,
50 | videoFormatABGR = 7,
51 | videoFormatARGB = 8,
52 |
53 | videoFormatYUY2 = 20, ///< yuv color formats
54 | videoFormatYVYU = 21,
55 | videoFormatUYVY = 22,
56 | videoFormatI420 = 23, ///< the same as IYUV
57 | videoFormatYV12 = 24,
58 | videoFormatInternal = 25, ///< only used in SVC decoder testbed
59 |
60 | videoFormatNV12 = 26, ///< new format for output by DXVA decoding
61 |
62 | videoFormatVFlip = 0x80000000
63 | } EVideoFormatType;
64 |
65 | /**
66 | * @brief Enumerate video frame type
67 | */
68 | typedef enum {
69 | videoFrameTypeInvalid, ///< encoder not ready or parameters are invalidate
70 | videoFrameTypeIDR, ///< IDR frame in H.264
71 | videoFrameTypeI, ///< I frame type
72 | videoFrameTypeP, ///< P frame type
73 | videoFrameTypeSkip, ///< skip the frame based encoder kernel
74 | videoFrameTypeIPMixed ///< a frame where I and P slices are mixing, not supported yet
75 | } EVideoFrameType;
76 |
77 | /**
78 | * @brief Enumerate return type
79 | */
80 | typedef enum {
81 | cmResultSuccess, ///< successful
82 | cmInitParaError, ///< parameters are invalid
83 | cmUnknownReason,
84 | cmMallocMemeError, ///< malloc a memory error
85 | cmInitExpected, ///< initial action is expected
86 | cmUnsupportedData
87 | } CM_RETURN;
88 |
89 | /**
90 | * @brief Enumulate the nal unit type
91 | */
92 | enum ENalUnitType {
93 | NAL_UNKNOWN = 0,
94 | NAL_SLICE = 1,
95 | NAL_SLICE_DPA = 2,
96 | NAL_SLICE_DPB = 3,
97 | NAL_SLICE_DPC = 4,
98 | NAL_SLICE_IDR = 5, ///< ref_idc != 0
99 | NAL_SEI = 6, ///< ref_idc == 0
100 | NAL_SPS = 7,
101 | NAL_PPS = 8
102 | ///< ref_idc == 0 for 6,9,10,11,12
103 | };
104 |
105 | /**
106 | * @brief NRI: eNalRefIdc
107 | */
108 | enum ENalPriority {
109 | NAL_PRIORITY_DISPOSABLE = 0,
110 | NAL_PRIORITY_LOW = 1,
111 | NAL_PRIORITY_HIGH = 2,
112 | NAL_PRIORITY_HIGHEST = 3
113 | };
114 |
115 | #define IS_PARAMETER_SET_NAL(eNalRefIdc, eNalType) \
116 | ( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == (NAL_SPS|NAL_PPS) || eNalType == NAL_SPS) )
117 |
118 | #define IS_IDR_NAL(eNalRefIdc, eNalType) \
119 | ( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == NAL_SLICE_IDR) )
120 |
121 | #define FRAME_NUM_PARAM_SET (-1)
122 | #define FRAME_NUM_IDR 0
123 |
124 | /**
125 | * @brief eDeblockingIdc
126 | */
127 | enum {
128 | DEBLOCKING_IDC_0 = 0,
129 | DEBLOCKING_IDC_1 = 1,
130 | DEBLOCKING_IDC_2 = 2
131 | };
132 | #define DEBLOCKING_OFFSET (6)
133 | #define DEBLOCKING_OFFSET_MINUS (-6)
134 |
135 | /* Error Tools definition */
136 | typedef unsigned short ERR_TOOL;
137 |
138 | /**
139 | @brief to do
140 | */
141 | enum {
142 | ET_NONE = 0x00, ///< NONE Error Tools
143 | ET_IP_SCALE = 0x01, ///< IP Scalable
144 | ET_FMO = 0x02, ///< Flexible Macroblock Ordering
145 | ET_IR_R1 = 0x04, ///< Intra Refresh in predifined 2% MB
146 | ET_IR_R2 = 0x08, ///< Intra Refresh in predifined 5% MB
147 | ET_IR_R3 = 0x10, ///< Intra Refresh in predifined 10% MB
148 | ET_FEC_HALF = 0x20, ///< Forward Error Correction in 50% redundency mode
149 | ET_FEC_FULL = 0x40, ///< Forward Error Correction in 100% redundency mode
150 | ET_RFS = 0x80 ///< Reference Frame Selection
151 | };
152 |
153 | /**
154 | * @brief Information of coded Slice(=NAL)(s)
155 | */
156 | typedef struct SliceInformation {
157 | unsigned char* pBufferOfSlices; ///< base buffer of coded slice(s)
158 | int iCodedSliceCount; ///< number of coded slices
159 | unsigned int* pLengthOfSlices; ///< array of slices length accordingly by number of slice
160 | int iFecType; ///< FEC type[0, 50%FEC, 100%FEC]
161 | unsigned char uiSliceIdx; ///< index of slice in frame [FMO: 0,..,uiSliceCount-1; No FMO: 0]
162 | unsigned char uiSliceCount; ///< count number of slice in frame [FMO: 2-8; No FMO: 1]
163 | char iFrameIndex; ///< index of frame[-1, .., idr_interval-1]
164 | unsigned char uiNalRefIdc; ///< NRI, priority level of slice(NAL)
165 | unsigned char uiNalType; ///< NAL type
166 | unsigned char
167 | uiContainingFinalNal; ///< whether final NAL is involved in buffer of coded slices, flag used in Pause feature in T27
168 | } SliceInfo, *PSliceInfo;
169 |
170 | /**
171 | * @brief thresholds of the initial, maximal and minimal rate
172 | */
173 | typedef struct {
174 | int iWidth; ///< frame width
175 | int iHeight; ///< frame height
176 | int iThresholdOfInitRate; ///< threshold of initial rate
177 | int iThresholdOfMaxRate; ///< threshold of maximal rate
178 | int iThresholdOfMinRate; ///< threshold of minimal rate
179 | int iMinThresholdFrameRate; ///< min frame rate min
180 | int iSkipFrameRate; ///< skip to frame rate min
181 | int iSkipFrameStep; ///< how many frames to skip
182 | } SRateThresholds, *PRateThresholds;
183 |
184 | /**
185 | * @brief Structure for decoder memery
186 | */
187 | typedef struct TagSysMemBuffer {
188 | int iWidth; ///< width of decoded pic for display
189 | int iHeight; ///< height of decoded pic for display
190 | int iFormat; ///< type is "EVideoFormatType"
191 | int iStride[2]; ///< stride of 2 component
192 | } SSysMEMBuffer;
193 |
194 | /**
195 | * @brief Buffer info
196 | */
197 | typedef struct TagBufferInfo {
198 | int iBufferStatus; ///< 0: one frame data is not ready; 1: one frame data is ready
199 | unsigned long long uiInBsTimeStamp; ///< input BS timestamp
200 | unsigned long long uiOutYuvTimeStamp; ///< output YUV timestamp, when bufferstatus is 1
201 | union {
202 | SSysMEMBuffer sSystemBuffer; ///< memory info for one picture
203 | } UsrData; ///< output buffer info
204 | unsigned char* pDst[3]; //point to picture YUV data
205 | } SBufferInfo;
206 |
207 |
208 | /**
209 | * @brief In a GOP, multiple of the key frame number, derived from
210 | * the number of layers(index or array below)
211 | */
212 | static const char kiKeyNumMultiple[] = {
213 | 1, 1, 2, 4, 8, 16,
214 | };
215 |
216 | #endif//WELS_VIDEO_CODEC_DEFINITION_H__
217 |
--------------------------------------------------------------------------------
/openh264-codec/src/main/jni/libopenh264/include/wels/codec_def.h:
--------------------------------------------------------------------------------
1 | /*!
2 | * \copy
3 | * Copyright (c) 2013, Cisco Systems
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | *
13 | * * Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in
15 | * the documentation and/or other materials provided with the
16 | * distribution.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | * POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | */
32 |
33 | #ifndef WELS_VIDEO_CODEC_DEFINITION_H__
34 | #define WELS_VIDEO_CODEC_DEFINITION_H__
35 |
36 | /**
37 | * @file codec_def.h
38 | */
39 |
40 | /**
41 | * @brief Enumerate the type of video format
42 | */
43 | typedef enum {
44 | videoFormatRGB = 1, ///< rgb color formats
45 | videoFormatRGBA = 2,
46 | videoFormatRGB555 = 3,
47 | videoFormatRGB565 = 4,
48 | videoFormatBGR = 5,
49 | videoFormatBGRA = 6,
50 | videoFormatABGR = 7,
51 | videoFormatARGB = 8,
52 |
53 | videoFormatYUY2 = 20, ///< yuv color formats
54 | videoFormatYVYU = 21,
55 | videoFormatUYVY = 22,
56 | videoFormatI420 = 23, ///< the same as IYUV
57 | videoFormatYV12 = 24,
58 | videoFormatInternal = 25, ///< only used in SVC decoder testbed
59 |
60 | videoFormatNV12 = 26, ///< new format for output by DXVA decoding
61 |
62 | videoFormatVFlip = 0x80000000
63 | } EVideoFormatType;
64 |
65 | /**
66 | * @brief Enumerate video frame type
67 | */
68 | typedef enum {
69 | videoFrameTypeInvalid, ///< encoder not ready or parameters are invalidate
70 | videoFrameTypeIDR, ///< IDR frame in H.264
71 | videoFrameTypeI, ///< I frame type
72 | videoFrameTypeP, ///< P frame type
73 | videoFrameTypeSkip, ///< skip the frame based encoder kernel
74 | videoFrameTypeIPMixed ///< a frame where I and P slices are mixing, not supported yet
75 | } EVideoFrameType;
76 |
77 | /**
78 | * @brief Enumerate return type
79 | */
80 | typedef enum {
81 | cmResultSuccess, ///< successful
82 | cmInitParaError, ///< parameters are invalid
83 | cmUnknownReason,
84 | cmMallocMemeError, ///< malloc a memory error
85 | cmInitExpected, ///< initial action is expected
86 | cmUnsupportedData
87 | } CM_RETURN;
88 |
89 | /**
90 | * @brief Enumulate the nal unit type
91 | */
92 | enum ENalUnitType {
93 | NAL_UNKNOWN = 0,
94 | NAL_SLICE = 1,
95 | NAL_SLICE_DPA = 2,
96 | NAL_SLICE_DPB = 3,
97 | NAL_SLICE_DPC = 4,
98 | NAL_SLICE_IDR = 5, ///< ref_idc != 0
99 | NAL_SEI = 6, ///< ref_idc == 0
100 | NAL_SPS = 7,
101 | NAL_PPS = 8
102 | ///< ref_idc == 0 for 6,9,10,11,12
103 | };
104 |
105 | /**
106 | * @brief NRI: eNalRefIdc
107 | */
108 | enum ENalPriority {
109 | NAL_PRIORITY_DISPOSABLE = 0,
110 | NAL_PRIORITY_LOW = 1,
111 | NAL_PRIORITY_HIGH = 2,
112 | NAL_PRIORITY_HIGHEST = 3
113 | };
114 |
115 | #define IS_PARAMETER_SET_NAL(eNalRefIdc, eNalType) \
116 | ( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == (NAL_SPS|NAL_PPS) || eNalType == NAL_SPS) )
117 |
118 | #define IS_IDR_NAL(eNalRefIdc, eNalType) \
119 | ( (eNalRefIdc == NAL_PRIORITY_HIGHEST) && (eNalType == NAL_SLICE_IDR) )
120 |
121 | #define FRAME_NUM_PARAM_SET (-1)
122 | #define FRAME_NUM_IDR 0
123 |
124 | /**
125 | * @brief eDeblockingIdc
126 | */
127 | enum {
128 | DEBLOCKING_IDC_0 = 0,
129 | DEBLOCKING_IDC_1 = 1,
130 | DEBLOCKING_IDC_2 = 2
131 | };
132 | #define DEBLOCKING_OFFSET (6)
133 | #define DEBLOCKING_OFFSET_MINUS (-6)
134 |
135 | /* Error Tools definition */
136 | typedef unsigned short ERR_TOOL;
137 |
138 | /**
139 | @brief to do
140 | */
141 | enum {
142 | ET_NONE = 0x00, ///< NONE Error Tools
143 | ET_IP_SCALE = 0x01, ///< IP Scalable
144 | ET_FMO = 0x02, ///< Flexible Macroblock Ordering
145 | ET_IR_R1 = 0x04, ///< Intra Refresh in predifined 2% MB
146 | ET_IR_R2 = 0x08, ///< Intra Refresh in predifined 5% MB
147 | ET_IR_R3 = 0x10, ///< Intra Refresh in predifined 10% MB
148 | ET_FEC_HALF = 0x20, ///< Forward Error Correction in 50% redundency mode
149 | ET_FEC_FULL = 0x40, ///< Forward Error Correction in 100% redundency mode
150 | ET_RFS = 0x80 ///< Reference Frame Selection
151 | };
152 |
153 | /**
154 | * @brief Information of coded Slice(=NAL)(s)
155 | */
156 | typedef struct SliceInformation {
157 | unsigned char* pBufferOfSlices; ///< base buffer of coded slice(s)
158 | int iCodedSliceCount; ///< number of coded slices
159 | unsigned int* pLengthOfSlices; ///< array of slices length accordingly by number of slice
160 | int iFecType; ///< FEC type[0, 50%FEC, 100%FEC]
161 | unsigned char uiSliceIdx; ///< index of slice in frame [FMO: 0,..,uiSliceCount-1; No FMO: 0]
162 | unsigned char uiSliceCount; ///< count number of slice in frame [FMO: 2-8; No FMO: 1]
163 | char iFrameIndex; ///< index of frame[-1, .., idr_interval-1]
164 | unsigned char uiNalRefIdc; ///< NRI, priority level of slice(NAL)
165 | unsigned char uiNalType; ///< NAL type
166 | unsigned char
167 | uiContainingFinalNal; ///< whether final NAL is involved in buffer of coded slices, flag used in Pause feature in T27
168 | } SliceInfo, *PSliceInfo;
169 |
170 | /**
171 | * @brief thresholds of the initial, maximal and minimal rate
172 | */
173 | typedef struct {
174 | int iWidth; ///< frame width
175 | int iHeight; ///< frame height
176 | int iThresholdOfInitRate; ///< threshold of initial rate
177 | int iThresholdOfMaxRate; ///< threshold of maximal rate
178 | int iThresholdOfMinRate; ///< threshold of minimal rate
179 | int iMinThresholdFrameRate; ///< min frame rate min
180 | int iSkipFrameRate; ///< skip to frame rate min
181 | int iSkipFrameStep; ///< how many frames to skip
182 | } SRateThresholds, *PRateThresholds;
183 |
184 | /**
185 | * @brief Structure for decoder memery
186 | */
187 | typedef struct TagSysMemBuffer {
188 | int iWidth; ///< width of decoded pic for display
189 | int iHeight; ///< height of decoded pic for display
190 | int iFormat; ///< type is "EVideoFormatType"
191 | int iStride[2]; ///< stride of 2 component
192 | } SSysMEMBuffer;
193 |
194 | /**
195 | * @brief Buffer info
196 | */
197 | typedef struct TagBufferInfo {
198 | int iBufferStatus; ///< 0: one frame data is not ready; 1: one frame data is ready
199 | unsigned long long uiInBsTimeStamp; ///< input BS timestamp
200 | unsigned long long uiOutYuvTimeStamp; ///< output YUV timestamp, when bufferstatus is 1
201 | union {
202 | SSysMEMBuffer sSystemBuffer; ///< memory info for one picture
203 | } UsrData; ///< output buffer info
204 | unsigned char* pDst[3]; //point to picture YUV data
205 | } SBufferInfo;
206 |
207 |
208 | /**
209 | * @brief In a GOP, multiple of the key frame number, derived from
210 | * the number of layers(index or array below)
211 | */
212 | static const char kiKeyNumMultiple[] = {
213 | 1, 1, 2, 4, 8, 16,
214 | };
215 |
216 | #endif//WELS_VIDEO_CODEC_DEFINITION_H__
217 |
--------------------------------------------------------------------------------
/app/src/main/java/com/androidyuan/ui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.androidyuan.ui;
2 |
3 | import android.text.Editable;
4 | import android.text.TextWatcher;
5 | import android.view.ViewGroup.LayoutParams;
6 | import android.widget.EditText;
7 | import android.widget.Toast;
8 | import io.github.brucewind.softcodec.RtmpHelper;
9 | import io.github.brucewind.softcodec.YUVHelper;
10 |
11 | import java.io.IOException;
12 |
13 | import android.annotation.SuppressLint;
14 | import android.app.Activity;
15 | import android.graphics.ImageFormat;
16 | import android.hardware.Camera;
17 | import android.hardware.Camera.PreviewCallback;
18 | import android.os.Bundle;
19 | import android.util.Log;
20 | import android.view.SurfaceHolder;
21 | import android.view.SurfaceView;
22 | import android.view.View;
23 | import android.view.WindowManager;
24 |
25 | import com.androidyuan.softcodec.R;
26 |
27 | import junit.framework.Assert;
28 |
29 | public class MainActivity extends Activity implements SurfaceHolder.Callback,
30 | PreviewCallback {
31 | private static final String TAG = "MainActivity";
32 |
33 | Camera mCamera;
34 | SurfaceHolder mPreviewHolder;
35 | byte[] mPreviewBuffer;
36 | //TODO obtain the a compatible set of size from camera.
37 | int width = 640;
38 | int height = 480;
39 | private final int VIDEOBITRATE = 512 *4;
40 | private final int FPS = 60;
41 | private RtmpHelper mRtmpHelper = new RtmpHelper();
42 | private String mRtmpPushUrl = "rtmp://192.168.50.14/live/live";
43 | private long mEncoderPointer = 0;
44 | private byte[] mH264Buff = null;
45 | private int mCurrentTime;
46 | private int encodeTime;
47 |
48 |
49 | private SurfaceView mSurfaveView;
50 | private EditText editText;
51 |
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 |
55 | super.onCreate(savedInstanceState);
56 |
57 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
58 | setContentView(R.layout.activity_main);
59 |
60 | mSurfaveView = (SurfaceView) this
61 | .findViewById(R.id.surfaceView);
62 | mPreviewHolder = mSurfaveView.getHolder();
63 |
64 | mPreviewHolder.addCallback(this);
65 |
66 |
67 | editText = (EditText) findViewById(R.id.edit_url);
68 | editText.setText(mRtmpPushUrl);
69 | editText.addTextChangedListener(new TextWatcher() {
70 | @Override
71 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
72 |
73 | }
74 |
75 | @Override
76 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
77 |
78 | }
79 |
80 | @Override
81 | public void afterTextChanged(Editable editable) {
82 | mRtmpPushUrl = editable.toString();
83 | }
84 | });
85 |
86 | findViewById(R.id.connect).setOnClickListener(
87 | new View.OnClickListener() {
88 | @Override
89 | public void onClick(View v) {
90 | v.setEnabled(false);
91 | editText.setEnabled(false);
92 | if (mRtmpHelper.rtmpOpen(mRtmpPushUrl) > 0) {
93 | Log.d(TAG, getString(R.string.tips_connect_successfully, mRtmpPushUrl));
94 | mCurrentTime = (int) (System.currentTimeMillis());
95 | findViewById(R.id.start).setEnabled(true);
96 | }
97 | else{
98 | v.setEnabled(true);
99 | editText.setEnabled(true);
100 | Toast.makeText(MainActivity.this,getString(R.string.tips_cannt_connect,
101 | mRtmpPushUrl),Toast.LENGTH_SHORT).show();
102 | }
103 | }
104 | });
105 |
106 | findViewById(R.id.start).setOnClickListener(
107 | new View.OnClickListener() {
108 | @Override
109 | public void onClick(View v) {
110 | v.setEnabled(false);
111 | startCamera();
112 | mRtmpHelper.startRecordeAudio(mCurrentTime);
113 | findViewById(R.id.stop).setEnabled(true);
114 | }
115 | });
116 |
117 | findViewById(R.id.stop).setOnClickListener(
118 | new View.OnClickListener() {
119 | @Override
120 | public void onClick(View v) {
121 | stopStreaming();
122 | mRtmpHelper.stopRecordeAudio();
123 | v.setEnabled(false);
124 | findViewById(R.id.connect).setEnabled(true);
125 | }
126 | });
127 |
128 | }
129 |
130 | @SuppressLint("InlinedApi")
131 | private void startCamera() {
132 |
133 | mEncoderPointer = mRtmpHelper.compressBegin(width, height, VIDEOBITRATE, FPS);
134 | if(mEncoderPointer==0){
135 | Toast.makeText(this,"encoder init error.",Toast.LENGTH_LONG).show();
136 | return;
137 | }
138 |
139 | mH264Buff = new byte[width * height * 8];
140 |
141 | mPreviewHolder.setFixedSize(width, height);
142 |
143 | int stride = (int) Math.ceil(width / 16.0f) * 16;
144 | int cStride = (int) Math.ceil(width / 32.0f) * 16;
145 | final int frameSize = stride * height;
146 | final int qFrameSize = cStride * height / 2;
147 |
148 | mPreviewBuffer = new byte[frameSize + qFrameSize * 2];
149 |
150 |
151 |
152 | LayoutParams layoutParams= mSurfaveView.getLayoutParams();
153 |
154 | layoutParams.width = height;
155 | layoutParams.height = width;
156 |
157 | mSurfaveView.setLayoutParams(layoutParams);
158 |
159 | try {
160 | mCamera = Camera.open();
161 | mCamera.setDisplayOrientation(90);
162 |
163 | mCamera.setPreviewDisplay(mPreviewHolder);
164 | Camera.Parameters params = mCamera.getParameters();
165 |
166 | params.setPreviewSize(width, height);
167 | params.setPreviewFormat(ImageFormat.NV21);//may selected codec not support this format.
168 | //自动对焦
169 | if (params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
170 | params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
171 | }
172 | mCamera.setParameters(params);
173 | mCamera.addCallbackBuffer(mPreviewBuffer);
174 | mCamera.setPreviewCallbackWithBuffer(this);
175 | mCamera.startPreview();
176 | } catch (IOException e) {
177 | e.printStackTrace();
178 | } catch (RuntimeException e) {
179 | e.printStackTrace();
180 | }
181 | }
182 |
183 |
184 |
185 |
186 | @Override
187 | public void onPreviewFrame(byte[] data, Camera camera) {
188 | // TODO Auto-generated method stub
189 |
190 | mCamera.addCallbackBuffer(mPreviewBuffer);
191 | byte[] i420bytes = YUVHelper.nv21ToI420(data, width, height);
192 | Assert.assertEquals(i420bytes.length,data.length);
193 |
194 | int result = mRtmpHelper.compressBuffer(mEncoderPointer,
195 | i420bytes,
196 | i420bytes.length,
197 | mH264Buff);
198 |
199 | }
200 |
201 | private void stopStreaming() {
202 | if (mCamera != null) {
203 | mCamera.setPreviewCallback(null);
204 | mCamera.stopPreview();
205 | mCamera.release();
206 | mCamera = null;
207 | }
208 |
209 | if(mEncoderPointer!=0){
210 | mRtmpHelper.rtmpStop();
211 | mRtmpHelper.compressEnd(mEncoderPointer);
212 | mEncoderPointer=0;
213 | }
214 | }
215 |
216 |
217 | @Override
218 | public void surfaceCreated(SurfaceHolder holder) {
219 |
220 | }
221 |
222 | @Override
223 | public void surfaceChanged(SurfaceHolder holder, int format,
224 | int width,
225 | int height) {
226 | Log.w(TAG,"onSurfaceChange : "+width +"x"+ height);
227 |
228 | }
229 |
230 | @Override
231 | public void surfaceDestroyed(SurfaceHolder holder) {
232 | // TODO Auto-generated method stub
233 | stopStreaming();
234 | Log.i(TAG, "surface destroyed");
235 | }
236 |
237 | @Override
238 | protected void onPause() {
239 | findViewById(R.id.stop).performClick();
240 | super.onPause();
241 | }
242 |
243 | }
--------------------------------------------------------------------------------