【Android 多媒体应用】使用MediaCodec解码使用SurfaceView显示视频
1.MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView; /**
* MediaCodec SurfaceHolder Example
* @author taehwan
*
*/
public class MainActivity extends Activity implements SurfaceHolder.Callback {
private VideoDecoderThread mVideoDecoder; private static final String FILE_PATH = Environment.getExternalStorageDirectory() + "/TopGirl.mp4"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); SurfaceView surfaceView = new SurfaceView(this);
surfaceView.getHolder().addCallback(this);
setContentView(surfaceView); mVideoDecoder = new VideoDecoderThread();
} @Override
public void surfaceCreated(SurfaceHolder holder) { } @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mVideoDecoder != null) {
if (mVideoDecoder.init(holder.getSurface(), FILE_PATH)) {
mVideoDecoder.start(); } else {
mVideoDecoder = null;
} }
} @Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mVideoDecoder != null) {
mVideoDecoder.close();
}
} }
2.VideoDecoderThread.java
import java.io.IOException;
import java.nio.ByteBuffer; import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface; public class VideoDecoderThread extends Thread {
private static final String VIDEO = "video/";
private static final String TAG = "VideoDecoder";
private MediaExtractor mExtractor;
private MediaCodec mDecoder; private boolean eosReceived; public boolean init(Surface surface, String filePath) {
eosReceived = false;
try {
mExtractor = new MediaExtractor();
mExtractor.setDataSource(filePath);
//分离出音轨和视轨
Log.d(TAG, "getTrackCount: " + mExtractor.getTrackCount() );
for (int i = 0; i < mExtractor.getTrackCount(); i++) {
MediaFormat format = mExtractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith(VIDEO)) {
mExtractor.selectTrack(i);
mDecoder = MediaCodec.createDecoderByType(mime);
try {
Log.d(TAG, "format : " + format);
mDecoder.configure(format, surface, null, 0 /* Decoder */); } catch (IllegalStateException e) {
Log.e(TAG, "codec '" + mime + "' failed configuration. " + e);
return false;
} mDecoder.start();
break;
}
} } catch (IOException e) {
e.printStackTrace();
} return true;
} @Override
public void run() {
BufferInfo info = new BufferInfo();
ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
mDecoder.getOutputBuffers(); boolean isInput = true;
boolean first = false;
long startWhen = 0; while (!eosReceived) {
if (isInput) {
int inputIndex = mDecoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
// fill inputBuffers[inputBufferIndex] with valid data
ByteBuffer inputBuffer = inputBuffers[inputIndex]; int sampleSize = mExtractor.readSampleData(inputBuffer, 0); if (mExtractor.advance() && sampleSize > 0) {
mDecoder.queueInputBuffer(inputIndex, 0, sampleSize, mExtractor.getSampleTime(), 0); } else {
Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
mDecoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isInput = false;
}
}
} int outIndex = mDecoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
mDecoder.getOutputBuffers();
break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " + mDecoder.getOutputFormat());
break; case MediaCodec.INFO_TRY_AGAIN_LATER:
// Log.d(TAG, "INFO_TRY_AGAIN_LATER");
break; default:
if (!first) {
startWhen = System.currentTimeMillis();
first = true;
}
try {
long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startWhen);
//Log.d(TAG, "info.presentationTimeUs : " + (info.presentationTimeUs / 1000) + " playTime: " + (System.currentTimeMillis() - startWhen) + " sleepTime : " + sleepTime); if (sleepTime > 0)
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} mDecoder.releaseOutputBuffer(outIndex, true /* Surface init */);
break;
} // All decoded frames have been rendered, we can stop playing now
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
} mDecoder.stop();
mDecoder.release();
mExtractor.release();
} public void close() {
eosReceived = true;
}
}
【Android 多媒体应用】使用MediaCodec解码使用SurfaceView显示视频的更多相关文章
- Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析
场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...
- 基于 VLC 的 Android 多媒体解决方案
前段时间项目中需要在 Android 中播放视频.流媒体.查看监控,就研究了一下 Android 多媒体解决方案. 查找了一下,大致有如下几种: Android MediaPlayer FFmpeg ...
- Android 中使用MediaRecorder进行录像详解(视频录制)
在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. package com.video; import java.io.IOException; import android.ap ...
- Android 多媒体视频播放一( 多媒体理解与经验分享)
前言 说到android的多媒体,一把辛酸一把泪,当初听说会多媒体的比较牛掰,公司也有需求,于是乎我也积极的加入研究android多媒体的行列,记得以前刚接触的时候,最开始还是比较头大的,主要是但是很 ...
- android 原生 MediaPlayer 和 MediaCodec 的区别和联系(三)
目录: (4)Android 官方网站 对 MediaCodec的介绍 注:编解码器特定数据(Code-specific Data,简写为csd) 部分结合网上资料加入了补充和个人理解.请悉知 ...
- Android在MediaMuxer和MediaCodec用例 - audio+video
在Android多媒体类,MediaMuxer和MediaCodec这是一个相对年轻,他们是JB 4.1和JB 4.3据介绍. 前者被用来产生一个混合的音频和视频的多媒体文件.的缺点是,现在可以只支持 ...
- Android多媒体开发-stagefright及AwesomePlayer相关知识梳理
android的多媒体框架中, stagefright其实是AwesomePlayer的代理,就是个皮包公司. status_t StagefrightPlayer::setDataSource( c ...
- Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2
1. 使用NDK去编译官方的FFmpeg原版的话,还得自己实现JNI层与Java层,工程量比较大.所以移植FFmpeg到Android平台时,可以移植一些已经实现JNI与JAVA层的开源项目,毕竟软件 ...
- Android多媒体框架图
Android多媒体整体架构图 MediaPlayer框架图 Camera框架图 SoundRecorder框架图 VideoCamera框架图 OpenCore与Skia ALSA Audio框架图 ...
随机推荐
- MySql基础学习-数据操作
对于数据的操作,无非是“增删该查”这几种操作. 1增加 数据的增加使用insert语句插入 语法:INSERT INTO TABLE_NAME(column1,column2,...)VALUES(v ...
- ASP.NET上传文件,已经上传的大小保存在session中,在另一个页面中读取session的值不行
想自己做个ASP.NET上传文件时显示进度条的, 按照自己的想法,其实也就是显示每次已经上传的字节,从网上找到一个方法是能够把文件变成流以后再慢慢写入的,我在那个循环写入的时候每循环一次都把已经上传的 ...
- java中finally的使用
以前认为finally没用,但是实际上在try使用中是不可缺少的.
- cpu和gpu的区别和联系是什么
cpu和gpu的区别和联系是什么 一.总结 一句话总结:CPU:复杂任务,核少,做串行,计算能力只是CPU很小的一部分,处理复杂逻辑: GPU:简单任务,核多,做并行(大吞吐量),做显卡的图象单元计算 ...
- 【LABVIEW到C#】2》database的操作(一)之 创建access和创建表单
namespace添加如下 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- 51nod 1099 贪心/思维
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1099 1099 任务执行顺序 基准时间限制:1 秒 空间限制:13107 ...
- 【WPF】命令系统
引言 在MVVM模式开发下,命令Command是编程中不可或缺的一部分.下面,我分3种场景简单介绍一下命令的用法. ViewModel中的命令 在ViewModel定义命令是最常用的用法,开发中几乎9 ...
- filter()和sort()这两个方法一块学习,案例中。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 实用工具类--第三方开源--Lazy
下载地址 :https://github.com/ddwhan0123/Lazy 工具 描述 AnimationUtils 动画工具类 AppUtils APP相关信息工具类 AssetDatabas ...
- _Meta 部分用法
model.UserInfo._meta.app_label #获取该类所在app的app名称 model.UserInfo._meta.model_name #获取该类对应表名(字符串类型) mod ...