Skip to content

Commit

Permalink
增加编码模块.
Browse files Browse the repository at this point in the history
  • Loading branch information
yhding committed Oct 26, 2017
1 parent 210960f commit c20f325
Show file tree
Hide file tree
Showing 9 changed files with 718 additions and 2 deletions.
157 changes: 157 additions & 0 deletions app/src/main/java/com/evomotion/modules/FrameWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.evomotion.modules;

import android.os.Environment;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
* Created by jephy on 7/22/17.
*/

public class FrameWriter {

private final static String TAG = "FrameWriter";

private final File defaultDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/UVCResource/temp_frame_0815_1026");

private File dir;
private int fileNum = 0;//文件命名计数

/**
* @param dir 帧数据存放路径
*/

public FrameWriter(File dir) {
this.dir = dir;
}

/**
* 默认初始化帧数据存放路径
*/
public FrameWriter() {
this.dir = defaultDir;
}

/**
* 将ByteBuffer数据写入到存储卡的特定目录
* @param byteBuffer 需要写入的数据
* @param destDir 写入的目录
* @return
*/
public boolean writeFrameToStorage(ByteBuffer byteBuffer,File destDir){

byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);

Log.d(TAG, "writeFile....数组长度。。。" + bytes.length);
if (null == destDir){
destDir = defaultDir;
}

if (!destDir.exists()) {
destDir.mkdirs();
}

File file = new File(destDir, "/" + fileNum + "_frame.txt");
FileOutputStream outputStream = null;
BufferedOutputStream bufferedOutputStream=null;
try {
outputStream = new FileOutputStream(file);
bufferedOutputStream = new BufferedOutputStream(outputStream);
// byte[] bytes = new byte[frame.remaining()];
// frame.get(bytes);
// outputStream.write(bytes);
bufferedOutputStream.write(bytes);
bufferedOutputStream.flush();
fileNum++;
return true;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
public boolean writeFrameToStorage(byte[] yData,byte[] uData,byte[] vData,File destDir){
if (null == destDir){
destDir = defaultDir;
}

if (!destDir.exists()) {
destDir.mkdir();
}

File file = new File(destDir, "/" + fileNum + "_frame.txt");
FileOutputStream outputStream = null;
BufferedOutputStream bufferedOutputStream=null;
try {
outputStream = new FileOutputStream(file);
bufferedOutputStream = new BufferedOutputStream(outputStream);

bufferedOutputStream.write(yData);
bufferedOutputStream.write(uData);
bufferedOutputStream.write(vData);

bufferedOutputStream.flush();
fileNum++;
return true;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}

/**
* 将data数据写入到存储卡的特定目录
* @param data 需要写入的数据
* @param destDir 写入的目录
* @return
*/
public boolean writeFrameToStorage(byte[] data,File destDir){

Log.d(TAG, "writeFile....数组长度。。。" + data.length);
if (null == destDir){
destDir = defaultDir;
}

if (!destDir.exists()) {
destDir.mkdir();
}

File file = new File(destDir, "/" + fileNum + "_frame.txt");
FileOutputStream outputStream = null;
BufferedOutputStream bufferedOutputStream=null;
try {
outputStream = new FileOutputStream(file);
bufferedOutputStream = new BufferedOutputStream(outputStream);
bufferedOutputStream.write(data);
bufferedOutputStream.flush();
fileNum++;
return true;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
30 changes: 28 additions & 2 deletions app/src/main/java/com/evomotion/modules/MediaCodecUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class MediaCodecUtil{
private ByteBuffer mSPS;
private ByteBuffer mPPS;
private boolean isInitedCodec = false;
private boolean isShowSurface = false;
// 需要解码的类型
private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video
private final static int TIME_INTERNAL = 5;
Expand Down Expand Up @@ -228,7 +229,11 @@ else if (bResolution == Boolean.FALSE) {
}
Log.i(TAG,"Codec configure.");
//配置MediaFormat以及需要显示的surface
mCodec.configure(mediaFormat, holder.getSurface(), null, 0);
if(isShowSurface) {
mCodec.configure(mediaFormat, holder.getSurface(), null, 0);
}else{
mCodec.configure(mediaFormat, null, null, 0);
}
}catch(Exception ex)
{
Log.e(TAG,"Codec configure Error.");
Expand Down Expand Up @@ -385,11 +390,26 @@ public boolean onFrame(byte[] buf, int offset, int length) {
if (outputBufferIndex < 0) {
Log.e(TAG,"outputBufferIndex = " + outputBufferIndex);
}
ByteBuffer[] outBuffers = mCodec.getOutputBuffers();
//循环解码,直到数据全部解码完成
while (outputBufferIndex >= 0) {
if(!isShowSurface) {
if (outputBufferIndex >= 0) {
ByteBuffer bb = outBuffers[outputBufferIndex];
if (mListener != null) {
mListener.onVideoDecode(bb, bufferInfo);
}
}
}

//logger.d("outputBufferIndex = " + outputBufferIndex);
//true : 将解码的数据显示到surface上
mCodec.releaseOutputBuffer(outputBufferIndex, true);
if(isShowSurface){
mCodec.releaseOutputBuffer(outputBufferIndex, true);
}else{
mCodec.releaseOutputBuffer(outputBufferIndex, false);
}


if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.e(TAG, "BUFFER_FLAG_END_OF_STREAM");
Expand All @@ -401,6 +421,12 @@ public boolean onFrame(byte[] buf, int offset, int length) {
return true;
}

private OnVideoDecodeListener mListener;

public void setVideoListener(OnVideoDecodeListener mOnVideoListener) {
this.mListener = mOnVideoListener;
}

/**
*停止解码,释放解码器
*/
Expand Down
74 changes: 74 additions & 0 deletions app/src/main/java/com/evomotion/modules/MediaEncodeInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.evomotion.modules;

import android.annotation.SuppressLint;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.util.Log;

import java.util.Arrays;

/**
* Created by zhanjunjun on 2017/10/26.
*/

public class MediaEncodeInfo {


private String TAG = MediaEncodeInfo.class.getName();

public void printAllCodec()
{String mimeType = "video/avc";
Log.i(TAG,"function getDeCodecInfo");
int numCodecs = MediaCodecList.getCodecCount();
MediaCodecInfo codecInfo = null;
for (int i = 0; i < numCodecs && codecInfo == null; i++) {
MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
if (!info.isEncoder()) {
continue;
}
String[] types = info.getSupportedTypes();
boolean found = false;
for (int j = 0; j < types.length && !found; j++) {
if (types[j].equals(mimeType)) {
found = true;
}
}
if (!found)
continue;
codecInfo = info;
checkSupportColorFormat(codecInfo);
}
}

//检查编解码器支持类型及格式
@SuppressLint("NewApi")
private int checkSupportColorFormat(MediaCodecInfo codecInfo) {
Log.i(TAG, "function checkSupportColorFormat");
String mimeType = "video/avc";
Log.e(TAG, "Found " + codecInfo.getName() + " supporting " + mimeType);

// Find a color profile that the codec supports
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
Log.e(TAG, "supported length-" + capabilities.colorFormats.length + " == " + Arrays.toString(capabilities.colorFormats));
ColorNameList nameList = new ColorNameList();
for (int i = 0; i < capabilities.colorFormats.length; i++) {
switch (capabilities.colorFormats[i]) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:

Log.i(TAG, "encode supported color format::" + capabilities.colorFormats[i] + " " + nameList.GetColorName(capabilities.colorFormats[i]));
break;
default:
Log.e(TAG, "unknown supported color format " + capabilities.colorFormats[i] + " " + nameList.GetColorName(capabilities.colorFormats[i]));
break;
}
}

return -1;
}

}
13 changes: 13 additions & 0 deletions app/src/main/java/com/evomotion/modules/OnVideoDecodeListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.evomotion.modules;

import android.media.MediaCodec;

import java.nio.ByteBuffer;

/**
* Created by zhanjunjun on 2017/10/25.
*/

public interface OnVideoDecodeListener {
void onVideoDecode(ByteBuffer bb, MediaCodec.BufferInfo bi);
}
18 changes: 18 additions & 0 deletions app/src/main/java/com/evomotion/modules/OnVideoEncodeListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.evomotion.modules;

import android.media.MediaCodec;

import java.nio.ByteBuffer;

/**
* @Title: OnVideoEncodeListener
* @Package com.youku.crazytogether.app.modules.sopCastV2.render
* @Description:
* @Author Jim
* @Date 16/4/4
* @Time 上午10:27
* @Version
*/
public interface OnVideoEncodeListener {
void onVideoEncode(ByteBuffer bb, MediaCodec.BufferInfo bi);
}
Loading

0 comments on commit c20f325

Please sign in to comment.