Android视频流数据硬件解码示例

打印 上一主题 下一主题

主题 1032|帖子 1032|积分 3096

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.视频解码类 
  1. import android.media.MediaCodec;
  2. import android.media.MediaFormat;
  3. import java.nio.ByteBuffer;
  4. public class VideoDecoder {
  5.     private MediaCodec mediaCodec;
  6.     public void initDecoder(String mimeType, int width, int height) throws IOException {
  7.         // 创建 MediaCodec 实例
  8.         mediaCodec = MediaCodec.createDecoderByType(mimeType);
  9.         // 配置 MediaCodec
  10.         MediaFormat mediaFormat = MediaFormat.createVideoFormat(mimeType, width, height);
  11.         mediaCodec.configure(mediaFormat, null, null, 0);
  12.         // 启动解码器
  13.         mediaCodec.start();
  14.     }
  15.     public void decode(byte[] inputData) {
  16.         // 获取输入缓冲区索引
  17.         int inputBufferIndex = mediaCodec.dequeueInputBuffer(10000);
  18.         if (inputBufferIndex >= 0) {
  19.             ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
  20.             inputBuffer.clear();
  21.             inputBuffer.put(inputData);
  22.             // 将数据提交到解码器
  23.             mediaCodec.queueInputBuffer(inputBufferIndex, 0, inputData.length, 0, 0);
  24.         }
  25.         // 获取输出缓冲区索引
  26.         MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  27.         int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
  28.         while (outputBufferIndex >= 0) {
  29.             ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
  30.             // 处理解码后的数据
  31.             // TODO: 将 outputBuffer 中的数据进行处理或渲染
  32.             // 释放输出缓冲区
  33.             mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
  34.             outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
  35.         }
  36.     }
  37.     public void release() {
  38.         // 停止并释放解码器
  39.         mediaCodec.stop();
  40.         mediaCodec.release();
  41.         mediaCodec = null;
  42.     }
  43. }
复制代码
2.视频渲染
  1. public class VideoPlayerActivity extends Activity {
  2.     private SurfaceView surfaceView;
  3.     private SurfaceHolder surfaceHolder;
  4.     @Override
  5.     protected void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.         setContentView(R.layout.activity_video_player);
  8.         surfaceView = findViewById(R.id.surface_view);
  9.         surfaceHolder = surfaceView.getHolder();
  10.         surfaceHolder.addCallback(new SurfaceHolder.Callback() {
  11.             @Override
  12.             public void surfaceCreated(SurfaceHolder holder) {
  13.                 // 初始化解码器并开始解码
  14.                 initMediaCodec(holder.getSurface());
  15.             }
  16.             @Override
  17.             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  18.             }
  19.             @Override
  20.             public void surfaceDestroyed(SurfaceHolder holder) {
  21.             }
  22.         });
  23.     }
  24. }
复制代码
  1. private MediaCodec mediaCodec;
  2. private void initMediaCodec(Surface surface) {
  3.     try {
  4.         mediaCodec = MediaCodec.createDecoderByType("video/avc");  // H.264
  5.         MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 1920, 1080);
  6.         mediaCodec.configure(mediaFormat, surface, null, 0);
  7.         mediaCodec.start();
  8.         // 启动解码线程
  9.         new Thread(new DecodeRunnable()).start();
  10.     } catch (IOException e) {
  11.         e.printStackTrace();
  12.     }
  13. }
复制代码
  1. private class DecodeRunnable implements Runnable {
  2.     @Override
  3.     public void run() {
  4.         while (true) {
  5.             int inputBufferIndex = mediaCodec.dequeueInputBuffer(10000);
  6.             if (inputBufferIndex >= 0) {
  7.                 ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
  8.                 // 读取视频数据到inputBuffer中
  9.                 int sampleSize = readSampleData(inputBuffer);
  10.                 if (sampleSize < 0) {
  11.                     // 视频数据读取结束
  12.                     mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
  13.                     break;
  14.                 } else {
  15.                     mediaCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
  16.                 }
  17.             }
  18.             MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  19.             int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
  20.             if (outputBufferIndex >= 0) {
  21.                 mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
  22.             }
  23.         }
  24.         mediaCodec.stop();
  25.         mediaCodec.release();
  26.     }
  27.     private int readSampleData(ByteBuffer inputBuffer) {
  28.         // 实现视频数据读取逻辑,例如从文件或网络流中读取
  29.         return sampleSize;
  30.     }
  31. }
复制代码
3.读取本地视频文件
  1. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
复制代码
  1. import android.media.MediaExtractor;
  2. import android.media.MediaFormat;
  3. import java.io.IOException;
  4. public class VideoReader {
  5.     public void readVideoData(String filePath) {
  6.         MediaExtractor extractor = new MediaExtractor();
  7.         try {
  8.             // 设置数据源(文件路径)
  9.             extractor.setDataSource(filePath);
  10.             // 获取轨道数量
  11.             int trackCount = extractor.getTrackCount();
  12.             for (int i = 0; i < trackCount; i++) {
  13.                 MediaFormat format = extractor.getTrackFormat(i);
  14.                 String mime = format.getString(MediaFormat.KEY_MIME);
  15.                 // 选择视频轨道
  16.                 if (mime.startsWith("video/")) {
  17.                     extractor.selectTrack(i);
  18.                     break;
  19.                 }
  20.             }
  21.             // 读取视频数据
  22.             while (true) {
  23.                 int sampleSize = extractor.readSampleData(byteBuffer, 0);
  24.                 if (sampleSize < 0) {
  25.                     // 读取完成
  26.                     break;
  27.                 }
  28.                 // 处理视频数据
  29.                 byte[] videoData = new byte[sampleSize];
  30.                 byteBuffer.get(videoData, 0, sampleSize);
  31.                 // 前进到下一个样本
  32.                 extractor.advance();
  33.             }
  34.         } catch (IOException e) {
  35.             e.printStackTrace();
  36.         } finally {
  37.             extractor.release();
  38.         }
  39.     }
  40. }
复制代码
4.从网络流读取视频数据:
实现MediaDataSource
  1. import android.media.MediaDataSource;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.net.HttpURLConnection;
  5. import java.net.URL;
  6. public class NetworkMediaDataSource extends MediaDataSource {
  7.     private InputStream inputStream;
  8.     public NetworkMediaDataSource(String urlStr) throws IOException {
  9.         URL url = new URL(urlStr);
  10.         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  11.         inputStream = connection.getInputStream();
  12.     }
  13.     @Override
  14.     public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
  15.         inputStream.skip(position);
  16.         return inputStream.read(buffer, offset, size);
  17.     }
  18.     @Override
  19.     public long getSize() throws IOException {
  20.         return -1; // 未知大小
  21.     }
  22.     @Override
  23.     public void close() throws IOException {
  24.         inputStream.close();
  25.     }
  26. }
复制代码
使用MediaExtractor读取网络视频数据
  1. import android.media.MediaExtractor;
  2. import android.media.MediaFormat;
  3. import java.io.IOException;
  4. public class NetworkVideoReader {
  5.     public void readNetworkVideoData(String urlStr) {
  6.         MediaExtractor extractor = new MediaExtractor();
  7.         try {
  8.             // 设置数据源(网络流)
  9.             NetworkMediaDataSource mediaDataSource = new NetworkMediaDataSource(urlStr);
  10.             extractor.setDataSource(mediaDataSource);
  11.             // 获取轨道数量
  12.             int trackCount = extractor.getTrackCount();
  13.             for (int i = 0; i < trackCount; i++) {
  14.                 MediaFormat format = extractor.getTrackFormat(i);
  15.                 String mime = format.getString(MediaFormat.KEY_MIME);
  16.                 // 选择视频轨道
  17.                 if (mime.startsWith("video/")) {
  18.                     extractor.selectTrack(i);
  19.                     break;
  20.                 }
  21.             }
  22.             // 读取视频数据
  23.             while (true) {
  24.                 int sampleSize = extractor.readSampleData(byteBuffer, 0);
  25.                 if (sampleSize < 0) {
  26.                     // 读取完成
  27.                     break;
  28.                 }
  29.                 // 处理视频数据
  30.                 byte[] videoData = new byte[sampleSize];
  31.                 byteBuffer.get(videoData, 0, sampleSize);
  32.                 // 前进到下一个样本
  33.                 extractor.advance();
  34.             }
  35.         } catch (IOException e) {
  36.             e.printStackTrace();
  37.         } finally {
  38.             extractor.release();
  39.         }
  40.     }
  41. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表