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显示视频的更多相关文章

  1. Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析

    场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...

  2. 基于 VLC 的 Android 多媒体解决方案

    前段时间项目中需要在 Android 中播放视频.流媒体.查看监控,就研究了一下 Android 多媒体解决方案. 查找了一下,大致有如下几种: Android MediaPlayer FFmpeg ...

  3. Android 中使用MediaRecorder进行录像详解(视频录制)

    在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. package com.video; import java.io.IOException; import android.ap ...

  4. Android 多媒体视频播放一( 多媒体理解与经验分享)

    前言 说到android的多媒体,一把辛酸一把泪,当初听说会多媒体的比较牛掰,公司也有需求,于是乎我也积极的加入研究android多媒体的行列,记得以前刚接触的时候,最开始还是比较头大的,主要是但是很 ...

  5. android 原生 MediaPlayer 和 MediaCodec 的区别和联系(三)

    目录:     (4)Android 官方网站 对 MediaCodec的介绍 注:编解码器特定数据(Code-specific Data,简写为csd) 部分结合网上资料加入了补充和个人理解.请悉知 ...

  6. Android在MediaMuxer和MediaCodec用例 - audio+video

    在Android多媒体类,MediaMuxer和MediaCodec这是一个相对年轻,他们是JB 4.1和JB 4.3据介绍. 前者被用来产生一个混合的音频和视频的多媒体文件.的缺点是,现在可以只支持 ...

  7. Android多媒体开发-stagefright及AwesomePlayer相关知识梳理

    android的多媒体框架中, stagefright其实是AwesomePlayer的代理,就是个皮包公司. status_t StagefrightPlayer::setDataSource( c ...

  8. Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2

    1. 使用NDK去编译官方的FFmpeg原版的话,还得自己实现JNI层与Java层,工程量比较大.所以移植FFmpeg到Android平台时,可以移植一些已经实现JNI与JAVA层的开源项目,毕竟软件 ...

  9. Android多媒体框架图

    Android多媒体整体架构图 MediaPlayer框架图 Camera框架图 SoundRecorder框架图 VideoCamera框架图 OpenCore与Skia ALSA Audio框架图 ...

随机推荐

  1. sqlserver设置具体的访问权限

    为具体的用户设置具体的访问权限 收藏 use 你的库名 go --新增用户 exec sp_addlogin 'test' --添加登录 exec sp_grantdbaccess N'test' - ...

  2. 安装SQL 2008失败 (win7 旗舰版 32位)

    本机系统 win7 32位 旗舰版 机器已经有sql 2005了,2008 不能安装成功,而且无任何错误提示. 那么通过windows install clean up (下载 windows ins ...

  3. python中的列表和字典(一)

    一. 列表 1. 列表的定义 [] 2. 列表特征:有序列表,可以包含任意内容,可以重复 3. 列表的赋值(顺序赋值):listA = [A, B, C] 4. 列表的取值:list[index]  ...

  4. MySQL 分区知识点(一 )

    前言: 查了下资料,关于 MySQL 分区的博文讲的详细的比较少,也不全,只好在官网去翻译英文文章看了.大体整理了一下记录起来: MySQL 分区类型: 1.RANGE 分区: // 这种类型的分区基 ...

  5. Ceph的现状

    转自:https://www.ustack.com/blog/ceph-distributed-block-storage/ 1. Ceph简介 Ceph是统一分布式存储系统,具有优异的性能.可靠性. ...

  6. LeetCode OJ:Triangle(三角形)

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  7. java学习笔记 --- 网络编程(网络的基础知识)

    1.网络模型: |--OSI(open stystem Interconnection开放式系统互连) |--特点: 是一种异构系统互连的分层结构:提供了控制互连系统交互规则的标准骨架:定义一种抽象结 ...

  8. hdoj-3342-Legal or Not(拓扑排序)

    题目链接 /* Name:hdoj-3342-Legal or Not Copyright: Author: Date: 2018/4/11 15:59:18 Description: 判断是否存在环 ...

  9. 树莓派视频监控 —— 使用 mjpg

    下载到树莓派本地: $ wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip $ unzip master.zip ...

  10. Storm的并行度、Grouping策略以及消息可靠处理机制简介

    转自:https://my.oschina.net/zc741520/blog/409949 概念: Workers (JVMs): 在一个节点上可以运行一个或多个独立的JVM 进程.一个Topolo ...