您的位置:首页 > 移动开发 > Android开发

Android 解码MediaCodec 播放H264 265

2017-11-21 15:16 405 查看
Eclipse 源码: 
http://download.csdn.net/detail/yulinxx/9732744
package io.vec.demo.mediacodec;

import java.io.IOException;
import java.nio.ByteBuffer;

import android.app.Activity;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class DecodeActivity extends Activity implements SurfaceHolder.Callback {
// private static final String strVideo =
// Environment.getExternalStorageDirectory() + "/test/xx.avi";
// private static final String strVideo =
// Environment.getExternalStorageDirectory() + "/test/test.wmv";
// private static final String strVideo =
// Environment.getExternalStorageDirectory() +
// "/netease/cloudmusic/Music/Alborada Del Inka - Vientos suaves.mp3";

// private static final String strVideo =
// Environment.getExternalStorageDirectory() +
// "/DCIM/Camera/VID_20161117_175920.mp4";
// private static final String strVideo =
// Environment.getExternalStorageDirectory() + "/test/H264_1080.mp4";
// private static final String strVideo =
// Environment.getExternalStorageDirectory() + "/test/H265_1080.mp4";
private static final String strVideo = Environment.getExternalStorageDirectory() + "/test/H265_1080.mp4";

private String TAG = "DecodeActivity";

private PlayerThread mPlayerThread = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SurfaceView sv = new SurfaceView(this);
sv.getHolder().addCallback(this);
setContentView(sv);
}

protected void onDestroy() {
super.onDestroy();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mPlayerThread == null) {
mPlayerThread = new PlayerThread(holder.getSurface());
mPlayerThread.start();
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mPlayerThread != null) {
mPlayerThread.interrupt();
}
}

// *****************************************************************
private class PlayerThread extends Thread {
private MediaExtractor mediaExtractor;
/** 用来读取音視频文件 提取器 */
private MediaCodec mediaCodec;
/** 用来解码 解碼器 */
private Surface surface;

public PlayerThread(Surface surface) {
this.surface = surface;
}

@Override
public void run() {
mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource(strVideo); // 设置数据源
} catch (IOException e1) {
e1.printStackTrace();
}

String mimeType = null;
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) { // 信道总数
MediaFormat format = mediaExtractor.getTrackFormat(i); // 音频文件信息
mimeType = format.getString(MediaFormat.KEY_MIME); // Video/AVC
// H 264
// Video/HEVC
// H265
// video/hevc
if (mimeType.startsWith("video/")) { // 视频信道
mediaExtractor.selectTrack(i); // 切换到视频信道

mediaCodec = MediaCodec.createDecoderByType(mimeType); // 创建解码器,提供数据输出
mediaCodec.configure(format, surface, null, 0);
break;
}

if (mimeType.startsWith("audio/")) { // 音频信道

}
}

if (mediaCodec == null) {
Log.e("DecodeActivity", "Can't find video info!");
return;
}

mediaCodec.start(); // 启动MediaCodec ,等待传入数据

ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers(); // 用来存放目标文件的数据
// 输入
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers(); // 解码后的数据
// 输出
BufferInfo info = new BufferInfo(); // 用于描述解码得到的byte[]数据的相关信息
boolean bIsEos = false;
long startMs = System.currentTimeMillis();

// ==========开始解码=============
while (!Thread.interrupted()) {

if (!bIsEos) {
int inIndex = mediaCodec.dequeueInputBuffer(10000);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
int nSampleSize = mediaExtractor.readSampleData(buffer, 0); // 读取一帧数据至buffer中
if (nSampleSize < 0) {
Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
mediaCodec.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
bIsEos = true;
} else {
// 填数据
mediaCodec.queueInputBuffer(inIndex, 0, nSampleSize, mediaExtractor.getSampleTime(), 0); // 通知MediaDecode解码刚刚传入的数据
mediaExtractor.advance(); // 继续下一取样
}
}
}

int outIndex = mediaCodec.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = mediaCodec.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("DecodeActivity", "New format " + mediaCodec.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
break;
default:
ByteBuffer buffer = outputBuffers[outIndex];
Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer);

// We use a very simple clock to keep the video FPS, or the
// video
// playback will be too fast
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
mediaCodec.releaseOutputBuffer(outIndex, true);
break;
}

// All decoded frames have been rendered, we can stop playing
// now
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
} // end while

mediaCodec.stop();
mediaCodec.release();
mediaExtractor.release();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

版权声明:----------------------------未经博主允许, 随意转载----------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: