|
【基础+代码流】在JAVA下利用MEDIACODEC进行硬解码
发表于 2016-10-12 17:06:17
浏览:11844
|
回复:6
打印
只看该作者
[复制链接]
楼主
- /****************************************************
- /* 利用原生SURFACE和MEDIACODEC进行本地文件播放和流媒体播放
- /*
- /*
- *****************************************************/
- package com.timestech.xplayer;
- import java.io.File;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.content.pm.ActivityInfo;
- import android.media.AudioManager;
- import android.media.MediaCodec;
- import android.media.MediaCodec.BufferInfo;
- import android.media.MediaExtractor;
- import android.media.MediaFormat;
- import android.net.Uri;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Surface;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.Window;
- import android.view.WindowManager;
- import android.view.WindowManager.LayoutParams;
- public class MainActivity extends Activity implements SurfaceHolder.Callback {
- private SurfaceView xSurface = null;
- private PlayerThread xPlayer = null;
- private TsRecv tR = null;
-
- private static final String videoUrl = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
- private static final String videoLocalUrl = "http://192.168.1.179:60000";
- private static final String videoPath = "/mnt/sdcard/Movies/std_p.ts";
-
- @SuppressLint("SdCardPath")
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏
- this.requestWindowFeature(Window.FEATURE_NO_TITLE);
- //沉浸模式
- getWindow().getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
- // 设置横屏 禁止翻转
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-
- // 禁止休眠
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
- setContentView(R.layout.activity_main);
- //----------------------------------------surfaceView播放视频----------------------------------------//
- xSurface = (SurfaceView)findViewById(R.id.surfaceView);
-
- /*
- LayoutParams lp = (LayoutParams) xSurface.getLayoutParams(); //导致闪退
- lp.width = 1280;
- lp.height = 647;
- xSurface.setLayoutParams(lp);
- */
-
- SurfaceHolder surfaceHolder = xSurface.getHolder(); //SurfaceHolder是SurfaceView的控制接口
- surfaceHolder.addCallback(this); //因为这个类实现了SurfaceHolder.Callback接口,所以回调参数直接this
- //surfaceHolder.setFixedSize(1280, 720); //显示的分辨率,不是surface的大小,不设置为视频默认
- }
- private class PlayerThread extends Thread {
- private MediaExtractor extractor;
- private MediaCodec decoder;
- private Surface surface;
- private boolean DEMUX_ANDROID = false;
- public PlayerThread(Surface surface) {
- this.surface = surface;
- }
-
- @Override
- public void run() {
- if(DEMUX_ANDROID)
- {
- ////////////////////MediaExtractor
- extractor = new MediaExtractor();
- try {
- extractor.setDataSource(videoPath);
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- for (int i = 0; i < extractor.getTrackCount(); i++) {
- MediaFormat format = extractor.getTrackFormat(i);
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (mime.startsWith("video/")) {
- extractor.selectTrack(i);
- decoder = MediaCodec.createDecoderByType(mime);
- decoder.configure(format, surface, null, 0);
- break;
- }
- }
- }
- else
- {
- tR = new TsRecv();
- tR.start(videoLocalUrl, 0);
-
- MediaFormat format;
- format = MediaFormat.createVideoFormat("video/avc", 1280, 720);
- String mime = format.getString(MediaFormat.KEY_MIME);
- decoder = MediaCodec.createDecoderByType(mime);
- decoder.configure(format, surface, null, 0);
- }
-
- if (decoder == null) {
- Log.e("DecodeActivity", "Can't find video info!");
- return;
- }
- decoder.start();
-
- ByteBuffer[] inputBuffers = decoder.getInputBuffers();
- ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
- BufferInfo info = new BufferInfo();
- long startMs = System.currentTimeMillis();
- int sampleSize = 0;
- boolean isEOS = false;
- while (true) {
- //if (!isEOS)
- {
- int inIndex = decoder.dequeueInputBuffer(10000);
- if (inIndex >= 0) {
- ByteBuffer buffer = inputBuffers[inIndex];
-
- if(DEMUX_ANDROID)
- {
- ////////////////////MediaExtractor
- sampleSize = extractor.readSampleData(buffer, 0);
- if (sampleSize < 0) {
- // We shouldn't stop the playback at this point, just pass the EOS
- // flag to decoder, we will get it again from the
- // dequeueOutputBuffer
- Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
- decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- isEOS = true;
- } else {
- /////////////////// MediaExtractor
- //Log.d("SAMPLESIZE", "SIZE["+sampleSize+"]");
- long timeus = extractor.getSampleTime();
- //Log.d("TIMESUS", "extractor.getSampleTime() is "+timeus);
- decoder.queueInputBuffer(inIndex, 0, sampleSize, timeus, 0);
- extractor.advance();
- }
- }
- else
- {
- sampleSize = tR.readSampleData(buffer);
-
- if (sampleSize <= 0) {
- // We shouldn't stop the playback at this point, just pass the EOS
- // flag to decoder, we will get it again from the
- // dequeueOutputBuffer
- Log.d("DecodeActivity", "###########################InputBuffer BUFFER_FLAG_END_OF_STREAM");
- //decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- } else {
- //Log.d("SAMPLESIZE", "SIZE["+sampleSize+"]");
- decoder.queueInputBuffer(inIndex, 0, sampleSize, 0, 0);
- //Log.d("DecodeActivity", "sampleSize "+sampleSize);
- }
- }
- }
- else
- continue;
- }
-
- int outIndex = decoder.dequeueOutputBuffer(info, 0);
- //Log.d("SAMPLESIZE", "OUTINDEX["+outIndex+"]");
- switch (outIndex) {
- case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
- //Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
- //outputBuffers = decoder.getOutputBuffers();
- break;
- case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
- //Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
- break;
- case MediaCodec.INFO_TRY_AGAIN_LATER:
- //Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
- break;
- default:
- if(DEMUX_ANDROID)
- {
- ////////////////////MediaExtractor
- 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
-
- //Log.v("DecodeActivity", "info.presentationTimeUs is " + info.presentationTimeUs/1000 + " currTimeMilli is " + System.currentTimeMillis() + " startMs is " + startMs);
- while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
- try {
- sleep(12);
- } catch (InterruptedException e) {
- e.printStackTrace();
- break;
- }
- }
- }
- else
- {
- try {
- sleep(30);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- decoder.releaseOutputBuffer(outIndex, true);
- break;
- }
-
- // All decoded frames have been rendered, we can stop playing now
-
- if(DEMUX_ANDROID)
- {
- ////////////////////MediaExtractor
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
- break;
- }
- }
- else
- {
-
-
- }
- }
-
- Log.d("PlayerThread:", "OVER.......................................");
-
- if(DEMUX_ANDROID)
- {
- ////////////////////MediaExtractor
- decoder.stop();
- decoder.release();
- extractor.release();
- }
- return ;
- }
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- if (xPlayer == null) {
- xPlayer = new PlayerThread(holder.getSurface());
- xPlayer.start();
- }
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- // TODO Auto-generated method stub
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- // TODO Auto-generated method stub
-
- }
-
- protected void onDestroy() {
- tR.stop();
- super.onDestroy();
- }
- }
复制代码 |
|