├── bin ├── Sayhi.apk ├── classes.dex ├── resources.ap_ ├── HardWareLive.apk ├── classes │ └── com │ │ └── jutong │ │ └── hardware │ │ └── live │ │ ├── R.class │ │ ├── R$attr.class │ │ ├── R$id.class │ │ ├── R$menu.class │ │ ├── AudioTag.class │ │ ├── R$layout.class │ │ ├── R$string.class │ │ ├── R$style.class │ │ ├── BuildConfig.class │ │ ├── R$drawable.class │ │ ├── AudioEncoder.class │ │ ├── MainActivity.class │ │ ├── VideoEncoder.class │ │ ├── MainActivity$1.class │ │ └── AudioSpecificConfig.class ├── jarlist.cache ├── res │ └── crunch │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ └── drawable-xxhdpi │ │ └── ic_launcher.png ├── dexedLibs │ ├── android-support-v4-8d03e1ee58754f9c9b7f17cccce13e7a.jar │ └── android-support-v4-b811133253323e12c3608a02dea6d8e5.jar └── AndroidManifest.xml ├── ic_launcher-web.png ├── libs ├── android-support-v4.jar └── armeabi-v7a │ └── libmyjni.so ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── values │ ├── strings.xml │ └── styles.xml ├── menu │ └── activity_main.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml └── layout │ └── activity_main.xml ├── gen └── com │ └── jutong │ └── hardware │ └── live │ ├── BuildConfig.java │ └── R.java ├── README.md ├── src └── com │ └── jutong │ └── hardware │ └── live │ ├── AudioTag.java │ ├── AudioSpecificConfig.java │ ├── MainActivity.java │ ├── AudioEncoder.java │ └── VideoEncoder.java ├── project.properties ├── proguard-project.txt └── AndroidManifest.xml /bin/Sayhi.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/Sayhi.apk -------------------------------------------------------------------------------- /bin/classes.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes.dex -------------------------------------------------------------------------------- /bin/resources.ap_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/resources.ap_ -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/ic_launcher-web.png -------------------------------------------------------------------------------- /bin/HardWareLive.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/HardWareLive.apk -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/libs/android-support-v4.jar -------------------------------------------------------------------------------- /libs/armeabi-v7a/libmyjni.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/libs/armeabi-v7a/libmyjni.so -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R.class -------------------------------------------------------------------------------- /bin/jarlist.cache: -------------------------------------------------------------------------------- 1 | # cache for current jar dependency. DO NOT EDIT. 2 | # format is 3 | # Encoding is UTF-8 4 | -------------------------------------------------------------------------------- /bin/res/crunch/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/res/crunch/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/crunch/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/res/crunch/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/crunch/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/res/crunch/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/crunch/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/res/crunch/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$attr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$attr.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$id.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$id.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$menu.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$menu.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/AudioTag.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/AudioTag.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$layout.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$layout.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$string.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$string.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$style.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$style.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/BuildConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/BuildConfig.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/R$drawable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/R$drawable.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/AudioEncoder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/AudioEncoder.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/MainActivity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/MainActivity.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/VideoEncoder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/VideoEncoder.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/MainActivity$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/MainActivity$1.class -------------------------------------------------------------------------------- /bin/classes/com/jutong/hardware/live/AudioSpecificConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/classes/com/jutong/hardware/live/AudioSpecificConfig.class -------------------------------------------------------------------------------- /bin/dexedLibs/android-support-v4-8d03e1ee58754f9c9b7f17cccce13e7a.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/dexedLibs/android-support-v4-8d03e1ee58754f9c9b7f17cccce13e7a.jar -------------------------------------------------------------------------------- /bin/dexedLibs/android-support-v4-b811133253323e12c3608a02dea6d8e5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-lance/MediaCodecPublisher/HEAD/bin/dexedLibs/android-support-v4-b811133253323e12c3608a02dea6d8e5.jar -------------------------------------------------------------------------------- /gen/com/jutong/hardware/live/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.jutong.hardware.live; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HardWareLive 2 | 使用android MediaCodec编码h264+aac上传rtmp服务器进行直播. 3 | 有精力再弄,由于没在jni层实现序列与线程。只能开启单独音频或者视频流. 4 | 流媒体服务器地址现在写死在了jni层。 5 | 6 | 7 | 使用x264+faac在android上进行推流可以查看:https://github.com/EarthXiang/LivePublisher 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MediaCodec编码 5 | Settings 6 | Hello world! 7 | 8 | -------------------------------------------------------------------------------- /res/menu/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /src/com/jutong/hardware/live/AudioTag.java: -------------------------------------------------------------------------------- 1 | package com.jutong.hardware.live; 2 | 3 | public class AudioTag { 4 | 5 | private byte[] data; 6 | 7 | private int currentBit = 0; 8 | 9 | public AudioTag() { 10 | data = new byte[2]; 11 | } 12 | 13 | public int getCurrentBit() { 14 | return currentBit; 15 | } 16 | 17 | public byte[] getData() { 18 | return data; 19 | } 20 | 21 | public void addCurrentBit(int currentBit) { 22 | this.currentBit += currentBit; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-23 15 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /bin/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/com/jutong/hardware/live/AudioSpecificConfig.java: -------------------------------------------------------------------------------- 1 | package com.jutong.hardware.live; 2 | 3 | public class AudioSpecificConfig { 4 | 5 | private final static int BYTE_NUMBIT = 8; 6 | 7 | private static void putByte(AudioTag audioTag, long data, int numBit) { 8 | long bits; 9 | int num = 0; 10 | int maxNum = BYTE_NUMBIT - audioTag.getCurrentBit() % BYTE_NUMBIT; 11 | int curNum = 0; 12 | while (num < numBit) { 13 | curNum = Math.min(numBit - num, maxNum); 14 | bits = data >> (numBit - num - curNum); 15 | WriteByte(audioTag, bits, curNum); 16 | num += curNum; 17 | maxNum = BYTE_NUMBIT; 18 | } 19 | } 20 | 21 | private static void WriteByte(AudioTag audioTag, long data, int numBit) { 22 | long numUsed, idx; 23 | idx = (audioTag.getCurrentBit() / BYTE_NUMBIT) % 2; 24 | numUsed = audioTag.getCurrentBit() % BYTE_NUMBIT; 25 | audioTag.getData()[(int) idx] |= (data & ((1 << numBit) - 1)) << (BYTE_NUMBIT 26 | - numUsed - numBit); 27 | audioTag.addCurrentBit(numBit); 28 | } 29 | 30 | private static int GetSRIndex(int sampleRate) { 31 | if (92017 <= sampleRate) 32 | return 0; 33 | if (75132 <= sampleRate) 34 | return 1; 35 | if (55426 <= sampleRate) 36 | return 2; 37 | if (46009 <= sampleRate) 38 | return 3; 39 | if (37566 <= sampleRate) 40 | return 4; 41 | if (27713 <= sampleRate) 42 | return 5; 43 | if (23004 <= sampleRate) 44 | return 6; 45 | if (18783 <= sampleRate) 46 | return 7; 47 | if (13856 <= sampleRate) 48 | return 8; 49 | if (11502 <= sampleRate) 50 | return 9; 51 | if (9391 <= sampleRate) 52 | return 10; 53 | 54 | return 11; 55 | } 56 | 57 | public static AudioTag getTag(int Obj, int sampleRate, int channel) { 58 | AudioTag audioTag = new AudioTag(); 59 | putByte(audioTag, Obj, 5); 60 | putByte(audioTag, GetSRIndex(sampleRate), 4); 61 | putByte(audioTag, channel, 4); 62 | return audioTag; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /gen/com/jutong/hardware/live/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.jutong.hardware.live; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int ic_launcher=0x7f020000; 15 | } 16 | public static final class id { 17 | public static final int menu_settings=0x7f070001; 18 | public static final int surface=0x7f070000; 19 | } 20 | public static final class layout { 21 | public static final int activity_main=0x7f030000; 22 | } 23 | public static final class menu { 24 | public static final int activity_main=0x7f060000; 25 | } 26 | public static final class string { 27 | public static final int app_name=0x7f040000; 28 | public static final int hello_world=0x7f040002; 29 | public static final int menu_settings=0x7f040001; 30 | } 31 | public static final class style { 32 | /** 33 | Base application theme, dependent on API level. This theme is replaced 34 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 35 | 36 | 37 | Theme customizations available in newer API levels can go in 38 | res/values-vXX/styles.xml, while customizations related to 39 | backward-compatibility can go here. 40 | 41 | 42 | Base application theme for API 11+. This theme completely replaces 43 | AppBaseTheme from res/values/styles.xml on API 11+ devices. 44 | 45 | API 11 theme customizations can go here. 46 | 47 | Base application theme for API 14+. This theme completely replaces 48 | AppBaseTheme from BOTH res/values/styles.xml and 49 | res/values-v11/styles.xml on API 14+ devices. 50 | 51 | API 14 theme customizations can go here. 52 | */ 53 | public static final int AppBaseTheme=0x7f050000; 54 | /** Application theme. 55 | All customizations that are NOT specific to a particular API-level can go here. 56 | */ 57 | public static final int AppTheme=0x7f050001; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/jutong/hardware/live/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.jutong.hardware.live; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.graphics.ImageFormat; 6 | import android.hardware.Camera; 7 | import android.hardware.Camera.PreviewCallback; 8 | import android.media.AudioFormat; 9 | import android.media.AudioRecord; 10 | import android.media.MediaRecorder; 11 | import android.os.Build; 12 | import android.os.Bundle; 13 | import android.view.SurfaceHolder; 14 | import android.view.SurfaceHolder.Callback; 15 | import android.view.SurfaceView; 16 | 17 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 18 | public class MainActivity extends Activity implements Callback, PreviewCallback { 19 | private SurfaceView surface; 20 | private Camera mCamera; 21 | private VideoEncoder avcEncoder; 22 | private AudioEncoder audioEncoder; 23 | 24 | static { 25 | System.loadLibrary("myjni"); 26 | } 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_main); 32 | surface = (SurfaceView) findViewById(R.id.surface); 33 | surface.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 34 | surface.getHolder().addCallback(this); 35 | avcEncoder = new VideoEncoder(); 36 | avcEncoder.connect(); 37 | audioEncoder = new AudioEncoder(); 38 | new Thread() { 39 | public void run() { 40 | int minBufferSize = AudioRecord.getMinBufferSize(44100, 41 | AudioFormat.CHANNEL_IN_MONO, 42 | AudioFormat.ENCODING_PCM_16BIT); 43 | AudioRecord audioRecord = new AudioRecord( 44 | MediaRecorder.AudioSource.MIC, 44100, 45 | AudioFormat.CHANNEL_IN_MONO, 46 | AudioFormat.ENCODING_PCM_16BIT, minBufferSize); 47 | audioRecord.startRecording(); 48 | while (true) { 49 | byte[] buffer = new byte[2048]; 50 | int len = audioRecord.read(buffer, 0, buffer.length); 51 | if (0 < len) { 52 | // audioEncoder.fireAudio(buffer, len); 53 | } 54 | } 55 | }; 56 | }.start(); 57 | } 58 | 59 | 60 | @Override 61 | public void surfaceCreated(SurfaceHolder holder) { 62 | 63 | 64 | 65 | } 66 | 67 | 68 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 69 | @Override 70 | public void surfaceChanged(SurfaceHolder holder, int format, int width, 71 | int height) { 72 | try { 73 | mCamera = Camera.open(0); 74 | Camera.Parameters parameters = mCamera.getParameters(); 75 | parameters.setPreviewSize(320, 240); 76 | avcEncoder.setVideoOptions(parameters.getPreviewSize().width, 77 | parameters.getPreviewSize().height, 320000, 25); 78 | parameters.setPreviewFormat(ImageFormat.NV21); 79 | mCamera.setParameters(parameters); 80 | mCamera.setPreviewCallback(this); 81 | mCamera.setPreviewDisplay(holder); 82 | mCamera.startPreview(); 83 | } catch (Exception ex) { 84 | ex.printStackTrace(); 85 | } 86 | 87 | } 88 | 89 | @Override 90 | public void surfaceDestroyed(SurfaceHolder holder) { 91 | 92 | } 93 | 94 | @Override 95 | public void onPreviewFrame(byte[] data, Camera camera) { 96 | avcEncoder.fireVideo(data); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/com/jutong/hardware/live/AudioEncoder.java: -------------------------------------------------------------------------------- 1 | package com.jutong.hardware.live; 2 | 3 | import java.io.IOException; 4 | import java.nio.ByteBuffer; 5 | import java.util.Arrays; 6 | 7 | import android.annotation.TargetApi; 8 | import android.media.MediaCodec; 9 | import android.media.MediaCodecInfo; 10 | import android.media.MediaCrypto; 11 | import android.media.MediaMuxer; 12 | import android.media.MediaCodecInfo.AudioCapabilities; 13 | import android.media.MediaFormat; 14 | import android.media.MediaCodecInfo.CodecCapabilities; 15 | import android.media.MediaCodecInfo.CodecProfileLevel; 16 | import android.media.MediaCodecList; 17 | import android.os.Build; 18 | import android.text.TextUtils; 19 | import android.util.Log; 20 | 21 | public class AudioEncoder { 22 | 23 | private final static String MINE_TYPE = "audio/mp4a-latm"; 24 | private MediaCodec mediaCodec; 25 | private String codecName; 26 | 27 | public AudioEncoder() { 28 | initialize(); 29 | } 30 | 31 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 32 | protected void initialize() { 33 | for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { 34 | MediaCodecInfo mediaCodecInfo = MediaCodecList.getCodecInfoAt(i); 35 | for (String type : mediaCodecInfo.getSupportedTypes()) { 36 | if (TextUtils.equals(type, MINE_TYPE) 37 | && mediaCodecInfo.isEncoder()) { 38 | codecName = mediaCodecInfo.getName(); 39 | break; 40 | } 41 | } 42 | if (null != codecName) { 43 | break; 44 | } 45 | } 46 | try { 47 | mediaCodec = MediaCodec.createByCodecName(codecName); 48 | MediaFormat mediaFormat = MediaFormat.createAudioFormat(MINE_TYPE, 49 | 44100, 1); 50 | mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 64000); 51 | mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, 52 | CodecProfileLevel.AACObjectLC); 53 | mediaCodec.configure(mediaFormat, null, null, 54 | MediaCodec.CONFIGURE_FLAG_ENCODE); 55 | mediaCodec.start(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | AudioTag audioTag = AudioSpecificConfig.getTag( 60 | CodecProfileLevel.AACObjectLC, 44100, 1); 61 | sendAAcTag(audioTag.getData()); 62 | } 63 | 64 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 65 | public void fireAudio(byte[] data, int len) { 66 | ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers(); 67 | ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers(); 68 | int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1); 69 | if (inputBufferIndex >= 0) { 70 | ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; 71 | inputBuffer.clear(); 72 | inputBuffer.put(data); 73 | mediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 74 | System.nanoTime(), 0); 75 | } 76 | MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); 77 | int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 78 | while (outputBufferIndex >= 0) { 79 | ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; 80 | byte[] outData = new byte[bufferInfo.size]; 81 | outputBuffer.get(outData); 82 | send(outData, bufferInfo.size); 83 | mediaCodec.releaseOutputBuffer(outputBufferIndex, false); 84 | outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 85 | } 86 | } 87 | 88 | private native void send(byte[] data, int leng); 89 | 90 | private native void sendAAcTag(byte[] data); 91 | } 92 | -------------------------------------------------------------------------------- /src/com/jutong/hardware/live/VideoEncoder.java: -------------------------------------------------------------------------------- 1 | package com.jutong.hardware.live; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.Arrays; 5 | 6 | import android.annotation.TargetApi; 7 | import android.media.MediaCodec; 8 | import android.media.MediaCodecInfo; 9 | import android.media.MediaCodecInfo.CodecCapabilities; 10 | import android.media.MediaCodecList; 11 | import android.media.MediaFormat; 12 | import android.os.Build; 13 | import android.text.TextUtils; 14 | import android.util.Log; 15 | 16 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 17 | public class VideoEncoder { 18 | 19 | private final static String MINE_TYPE = "video/avc"; 20 | private MediaCodec mediaCodec; 21 | private int mWidth; 22 | private int mHeight; 23 | private int mBit; 24 | private int mFps; 25 | private byte[] sps; 26 | private byte[] pps; 27 | private byte[] h264; 28 | private String codecName; 29 | 30 | 31 | 32 | public VideoEncoder() { 33 | initialize(); 34 | } 35 | 36 | protected void initialize() { 37 | for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { 38 | MediaCodecInfo mediaCodecInfo = MediaCodecList.getCodecInfoAt(i); 39 | for (String type : mediaCodecInfo.getSupportedTypes()) { 40 | if (TextUtils.equals(type, MINE_TYPE) 41 | && mediaCodecInfo.isEncoder()) { 42 | CodecCapabilities codecCapabilities = mediaCodecInfo 43 | .getCapabilitiesForType(MINE_TYPE); 44 | for (int format : codecCapabilities.colorFormats) { 45 | if (format == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar) { 46 | codecName = mediaCodecInfo.getName(); 47 | return; 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | public boolean isSupport() { 56 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 57 | 58 | } 59 | return false; 60 | } 61 | 62 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 63 | public void setVideoOptions(int width, int height, int bit, int fps) { 64 | mWidth = width; 65 | mHeight = height; 66 | mBit = bit; 67 | mFps = fps; 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 69 | try { 70 | mediaCodec = MediaCodec.createByCodecName(codecName); 71 | MediaFormat mediaFormat = MediaFormat.createVideoFormat( 72 | MINE_TYPE, width, height); 73 | 74 | mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bit); 75 | mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, fps); 76 | mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 关键帧间隔时间 77 | // 单位s 78 | mediaFormat 79 | .setInteger( 80 | MediaFormat.KEY_COLOR_FORMAT, 81 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar); 82 | // mediaFormat.setInteger(MediaFormat.KEY_PROFILE, 83 | // CodecProfileLevel.AVCProfileBaseline); 84 | // mediaFormat.setInteger(MediaFormat.KEY_LEVEL, 85 | // CodecProfileLevel.AVCLevel52); 86 | mediaCodec.configure(mediaFormat, null, null, 87 | MediaCodec.CONFIGURE_FLAG_ENCODE); 88 | mediaCodec.start(); 89 | } catch (Exception e) { 90 | System.out.println(e.getMessage()); 91 | e.printStackTrace(); 92 | } 93 | } 94 | } 95 | 96 | public void fireVideo(byte[] data) { 97 | h264 = new byte[mWidth * mHeight * 3 / 2]; 98 | byte[] rawData = nv212nv12(data); 99 | // 获得编码器输入输出数据缓存区 API:21之后可以使用 100 | // mediaCodec.getInputBuffer(mediaCodec.dequeueInputBuffer(-1));直接获得缓存数据 101 | ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers(); 102 | ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers(); 103 | // 获得有效输入缓存区数组下标 -1表示一直等待 104 | int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1); 105 | Log.d("DEMO", "输入:" + inputBufferIndex); 106 | if (inputBufferIndex >= 0) { 107 | // 将原始数据填充 inputbuffers 108 | ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; 109 | inputBuffer.clear(); 110 | inputBuffer.put(rawData); 111 | //将此数据加入编码队列 参数3:需要一个增长的时间戳,不然无法持续编码 112 | mediaCodec.queueInputBuffer(inputBufferIndex, 0, rawData.length, 113 | System.nanoTime(), 0); 114 | } 115 | //获得编码后的数据 116 | MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); 117 | //有效数据下标 118 | int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 119 | Log.d("DEMO", "输出:" + outputBufferIndex); 120 | while (outputBufferIndex >= 0) { 121 | ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; 122 | byte[] outData = new byte[bufferInfo.size]; 123 | outputBuffer.get(outData); 124 | System.out.println("type:" + outData[4]); 125 | if ((outData[4] & 0x1f) == 7) { // sps pps MediaCodec会在编码第一帧之前输出sps+pps sps pps加在一起 126 | // sps = new byte[outData.length - 4]; 127 | // System.arraycopy(outData, 4, sps, 0, outData.length - 4); 128 | Log.d("DEMO", "sps pps:" + Arrays.toString(outData)); 129 | for (int i = 0; i < outData.length; i++) { 130 | if (i + 4 < outData.length) { // 保证不越界 131 | if (outData[i] == 0x00 && outData[i + 1] == 0x00 132 | && outData[i + 2] == 0x00 133 | && outData[i + 3] == 0x01) { 134 | //在这里将sps pps分开 135 | // if ((outData[i + 4] & 0x1f) == 7) { // & 0x1f =7 136 | // sps 137 | // 138 | // } else 139 | //sps pps数据如下: 0x00 0x00 0x00 0x01 7 sps 0x00 0x00 0x00 0x01 8 pps 140 | if ((outData[i + 4] & 0x1f) == 8) {// & 0x1f =8 pps 141 | //去掉界定符 142 | sps = new byte[i - 4]; 143 | System.arraycopy(outData, 4, sps, 0, sps.length); 144 | pps = new byte[outData.length 145 | - (4 + sps.length) - 4]; 146 | System.arraycopy(outData, 4 + sps.length + 4, 147 | pps, 0, pps.length); 148 | break; 149 | } 150 | } 151 | } 152 | } 153 | Log.d("DEMO", "sps :" + Arrays.toString(sps)); 154 | Log.d("DEMO", "sps :" + Arrays.toString(pps)); 155 | } else { 156 | // (outData[4] & 0x1f) == 5) 关键帧 outData[4] == 0x65 157 | System.arraycopy(outData, 4, h264, 0, outData.length - 4); 158 | Log.d("DEMO", outData.length + ""); 159 | Log.d("DEMO", "帧数据 sps:" + sps.length + " pps:" + pps.length 160 | + " 264:" + h264.length); 161 | send(sps, pps, h264, sps.length, pps.length, outData.length - 4); 162 | } 163 | // if (sps_pps != null) { // 已经获得过sps pps 164 | // System.arraycopy(outData, 0, h264, 0, outData.length); 165 | // if (h264[4] == 0x65) {// 关键帧 h264[4]&0x1f==5 关键帧 166 | // Log.d("DEMO", "关键帧"); 167 | // } else { 168 | // Log.d("DEMO", "不是关键帧"); 169 | // } 170 | // send(sps_pps, h264); 171 | // } else { 172 | // ByteBuffer spsPpsBuffer = ByteBuffer.wrap(outData); 173 | // // 0x00 0x00 0x00 0x01 174 | // if (spsPpsBuffer.getInt() == 0x00000001) { 175 | // sps_pps = new byte[outData.length]; 176 | // System.arraycopy(outData, 0, sps_pps, 0, outData.length); 177 | // Log.d("DEMO", "sps pps信息"); 178 | // } else { 179 | // Log.d("DEMO", "错误 未获得sps pps信息 丢帧"); 180 | // } 181 | // } 182 | // 释放编码后的数据 183 | mediaCodec.releaseOutputBuffer(outputBufferIndex, false); 184 | // 重新获得编码bytebuffer下标 185 | outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); 186 | Log.d("DEMO", "完成 输出:" + outputBufferIndex); 187 | } 188 | // send(sps_pps, h264); 189 | // mediaCodec.flush(); 190 | } 191 | 192 | private native void send(byte[] sps, byte[] pps, byte[] h264, int sps_len, 193 | int pps_len, int h264_len); 194 | 195 | private native void conversjni(byte[] data, byte[] rawData); 196 | 197 | public native void connect(); 198 | 199 | private byte[] nv212nv12(byte[] data) { 200 | int len = mWidth * mHeight; 201 | byte[] buffer = new byte[len * 3 / 2]; 202 | byte[] y = new byte[len]; 203 | byte[] uv = new byte[len / 2]; 204 | System.arraycopy(data, 0, y, 0, len); 205 | for (int i = 0; i < len / 4; i++) { 206 | uv[i * 2] = data[len + i * 2 + 1]; 207 | uv[i * 2 + 1] = data[len + i * 2]; 208 | } 209 | System.arraycopy(y, 0, buffer, 0, y.length); 210 | System.arraycopy(uv, 0, buffer, y.length, uv.length); 211 | return buffer; 212 | } 213 | 214 | } 215 | --------------------------------------------------------------------------------