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. 项目开发之git配置

    1.本地安装git配置 安装步骤,这里不详细介绍,软件下载然后安装即可. 查看git安装版本 #git --version 2.git密钥生成 ssh-keygen -t rsa -C "f ...

  2. demo(幸福大转盘)总结

    百度推广首页demo 在<head>与</head>之间加入代码 <link rel="shortcut icon" href="favic ...

  3. PHP 5.2、5.3、5.4、5.5、5.6 版本区别对比以及新功能详解

    截至目前(2015.1), PHP 的最新稳定版本是 PHP5.5, 但有差不多一半的用户仍在使用已经不在维护  的 PHP5.2, 其余的一半用户在使用 PHP5.3 . 因为 PHP 那“集百家之 ...

  4. hdu6237 分解质因子

    题意:给一堆石子,每次移动一颗到另一堆,要求最小次数使得,所有石子数gcd>1 题解:枚举所有质因子,然后找次数最小的那一个,统计次数时,我们可以事先记录下每堆石子余质因子 的和,对所有石子取余 ...

  5. vue项目中引入element-ui时,如何更改主题色

    在我们做项目时,我们经常会遇到切换主题色的功能,下面我们就来说一下通过颜色选择器我们就能改变项目的主题颜色 代码如下: 颜色选择器所在组件: top-theme.vue内容如下: <templa ...

  6. python编程实例-统计apache进程占用的物理内存

    #!/usr/bin/env python import os from subprocess import PIPE,Popen def getPids(): p = Popen(['pidof', ...

  7. Java使用指南(1)—— Java下载和安装

    Java下载 1.在Oracle的官网中找到相应的

  8. 进程、线程、ThreadLlocal

    1.线程是最小的执行单位,而进程中至少一个线程组:如果调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间 Unix/Linux操作系统提供了一个fork()系统调用,它非常 ...

  9. web 压力测试工具ab压力测试详解

    Web性能压力测试工具之ApacheBench(ab)详解 原文:http://www.ha97.com/4617.html PS:网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压 ...

  10. THUSC 2017 大魔法师

    一个序列,每个物品有三个权值 $A,B,C$ 要求维护: 1.区间 $A_i+=B_i$ 2.区间 $B_i+=C_i$ 3.区间 $C_i+=A_i$ 4.区间 $A_i+=v$ 5.区间 $B_i ...