当前位置: 首页 > news >正文

威海千淼网站建设产品推广策略

威海千淼网站建设,产品推广策略,wordpress整合播放器,用java做计算机销售网站开发使用MediaCodec目的 MediaCodec是Android底层多媒体框架的一部分,通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,可以编码H264、H265、AAC、3gp等常见的音视频格式 MediaCodec工作原理是处理输入数据以产生输出数据 MediaCodec工作流程 Med…

使用MediaCodec目的

MediaCodec是Android底层多媒体框架的一部分,通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,可以编码H264、H265、AAC、3gp等常见的音视频格式

MediaCodec工作原理是处理输入数据以产生输出数据

MediaCodec工作流程

MediaCodec的数据流分为input和output流,并通过异步的方式处理两路数据流,直到手动释放output缓冲区,MediaCodec才将数据处理完毕

  • input流:客户端输入待解码或者待编码的数据
  • output流:客户端输出的已解码或者已编码的数据

MediaCodec API说明

  • getInputBuffers:获取需要输入流队列,返回ByteBuffer数组
  • queueInputBuffer:输入流入队
  • dequeueInputBuffer: 从输入流队列中取数据进行编码操作
  • getOutputBuffers:获取已经编解码之后的数据输出流队列,返回ByteBuffer数组
  • dequeueOutputBuffer:从输出队列中取出已经编码操作之后的数据
  • releaseOutputBuffer: 处理完成,释放output缓冲区

基本流程

  • MediaCodec的基本使用遵循上图所示,它的生命周期如下所示:
  • Stoped:创建好MediaCodec,进行配置,或者出现错误
  • Uninitialized: 当创建了一个MediaCodec对象,此时MediaCodec处于Uninitialized,在任何状态调用reset()方法使MediaCodec返回到Uninitialized状态
  • Configured: 使用configure(…)方法对MediaCodec进行配置转为Configured状态
  • Error: 出现错误
  • Executing:可以在Executing状态的任何时候通过调用flush()方法返回到Flushed状态
  • Flushed:调用start()方法后MediaCodec立即进入Flushed状态
  • Running:调用dequeueInputBuffer后,MediaCodec就转入Running状态
  • End-of-Stream:编解码结束后,MediaCodec将转入End-of-Stream子状态
  • Released:当使用完MediaCodec后,必须调用release()方法释放其资源

基本使用

//解码器
val mVideoDecoder = MediaCodec.createDecoderByType("video/avc")
//编码器
val mVideoEncoder = MediaCodec.createEncoderByType("video/avc")

MediaCodec 解码H264/H265

使用MediaCodec 解码H264/H265码流视频,那必须谈下MediaCodec这个神器。附官网数据流程图如下:

input:ByteBuffer输入方;

output:ByteBuffer输出方;

  • 使用者从MediaCodec请求一个空的输入buffer(ByteBuffer),填充满数据后将它传递给MediaCodec处理。
  • MediaCodec处理完这些数据并将处理结果输出至一个空的输出buffer(ByteBuffer)中。
  • 使用者从MediaCodec获取输出buffer的数据,消耗掉里面的数据,使用完输出buffer的数据之后,将其释放回编解码。

H264码流解码示例代码如下(基本都做了注释)

package com.zqfdev.h264decodedemo;
​
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;
​
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
​
/*** @author zhangqingfa* @createDate 2020/12/10 11:39* @description 解码H264播放*/
public class H264DeCodePlay {
​private static final String TAG = "zqf-dev";//视频路径private String videoPath;//使用android MediaCodec解码private MediaCodec mediaCodec;private Surface surface;
​H264DeCodePlay(String videoPath, Surface surface) {this.videoPath = videoPath;this.surface = surface;initMediaCodec();}
​private void initMediaCodec() {try {Log.e(TAG, "videoPath " + videoPath);//创建解码器 H264的Type为  AACmediaCodec = MediaCodec.createDecoderByType("video/avc");//创建配置MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 540, 960);//设置解码预期的帧速率【以帧/秒为单位的视频格式的帧速率的键】mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);//配置绑定mediaFormat和surfacemediaCodec.configure(mediaFormat, surface, null, 0);} catch (IOException e) {e.printStackTrace();//创建解码失败Log.e(TAG, "创建解码失败");}}
​/*** 解码播放*/void decodePlay() {mediaCodec.start();new Thread(new MyRun()).start();}
​private class MyRun implements Runnable {
​@Overridepublic void run() {try {//1、IO流方式读取h264文件【太大的视频分批加载】byte[] bytes = null;bytes = getBytes(videoPath);Log.e(TAG, "bytes size " + bytes.length);//2、拿到 mediaCodec 所有队列buffer[]ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();//开始位置int startIndex = 0;//h264总字节数int totalSize = bytes.length;//3、解析while (true) {//判断是否符合if (totalSize == 0 || startIndex >= totalSize) {break;}//寻找索引int nextFrameStart = findByFrame(bytes, startIndex + 1, totalSize);if (nextFrameStart == -1) break;MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();// 查询10000毫秒后,如果dSP芯片的buffer全部被占用,返回-1;存在则大于0int inIndex = mediaCodec.dequeueInputBuffer(10000);if (inIndex >= 0) {//根据返回的index拿到可以用的bufferByteBuffer byteBuffer = inputBuffers[inIndex];//清空缓存byteBuffer.clear();//开始为buffer填充数据byteBuffer.put(bytes, startIndex, nextFrameStart - startIndex);//填充数据后通知mediacodec查询inIndex索引的这个buffer,mediaCodec.queueInputBuffer(inIndex, 0, nextFrameStart - startIndex, 0, 0);//为下一帧做准备,下一帧首就是前一帧的尾。startIndex = nextFrameStart;} else {//等待查询空的buffercontinue;}//mediaCodec 查询 "mediaCodec的输出方队列"得到索引int outIndex = mediaCodec.dequeueOutputBuffer(info, 10000);Log.e(TAG, "outIndex " + outIndex);if (outIndex >= 0) {try {//暂时以休眠线程方式放慢播放速度Thread.sleep(33);} catch (InterruptedException e) {e.printStackTrace();}//如果surface绑定了,则直接输入到surface渲染并释放mediaCodec.releaseOutputBuffer(outIndex, true);} else {Log.e(TAG, "没有解码成功");}}} catch (IOException e) {e.printStackTrace();}}}
​
​//读取一帧数据private int findByFrame(byte[] bytes, int start, int totalSize) {for (int i = start; i < totalSize - 4; i++) {//对output.h264文件分析 可通过分隔符 0x00000001 读取真正的数据if (bytes[i] == 0x00 && bytes[i + 1] == 0x00 && bytes[i + 2] == 0x00 && bytes[i + 3] == 0x01) {return i;}}return -1;}private byte[] getBytes(String videoPath) throws IOException {InputStream is = new DataInputStream(new FileInputStream(new File(videoPath)));int len;int size = 1024;byte[] buf;ByteArrayOutputStream bos = new ByteArrayOutputStream();buf = new byte[size];while ((len = is.read(buf, 0, size)) != -1)bos.write(buf, 0, len);buf = bos.toByteArray();return buf;}
}

H265示例代码如下

package com.zqfdev.h264decodedemo;
​
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;
​
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
​
/*** @author zhangqingfa* @createDate 2020/12/10 11:39* @description 解码H264播放*/
public class H265DeCodePlay {
​private static final String TAG = "zqf-dev";//视频路径private String videoPath;//使用android MediaCodec解码private MediaCodec mediaCodec;private Surface surface;
​H265DeCodePlay(String videoPath, Surface surface) {this.videoPath = videoPath;this.surface = surface;initMediaCodec();}
​private void initMediaCodec() {try {Log.e(TAG, "videoPath " + videoPath);//创建解码器 H264的Type为  AACmediaCodec = MediaCodec.createDecoderByType("video/hevc");//创建配置MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/hevc", 368, 384);//设置解码预期的帧速率【以帧/秒为单位的视频格式的帧速率的键】mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);//配置绑定mediaFormat和surfacemediaCodec.configure(mediaFormat, surface, null, 0);} catch (IOException e) {e.printStackTrace();//创建解码失败Log.e(TAG, "创建解码失败");}}
​/*** 解码播放*/void decodePlay() {mediaCodec.start();new Thread(new MyRun()).start();}
​private class MyRun implements Runnable {
​@Overridepublic void run() {try {//1、IO流方式读取h264文件【太大的视频分批加载】byte[] bytes = null;bytes = getBytes(videoPath);Log.e(TAG, "bytes size " + bytes.length);//2、拿到 mediaCodec 所有队列buffer[]ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();//开始位置int startIndex = 0;//h264总字节数int totalSize = bytes.length;//3、解析while (true) {//判断是否符合if (totalSize == 0 || startIndex >= totalSize) {break;}//寻找索引int nextFrameStart = findByFrame(bytes, startIndex + 1, totalSize);if (nextFrameStart == -1) break;Log.e(TAG, "nextFrameStart " + nextFrameStart);MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();// 查询10000毫秒后,如果dSP芯片的buffer全部被占用,返回-1;存在则大于0int inIndex = mediaCodec.dequeueInputBuffer(10000);if (inIndex >= 0) {//根据返回的index拿到可以用的bufferByteBuffer byteBuffer = inputBuffers[inIndex];//清空byteBuffer缓存byteBuffer.clear();//开始为buffer填充数据byteBuffer.put(bytes, startIndex, nextFrameStart - startIndex);//填充数据后通知mediacodec查询inIndex索引的这个buffer,mediaCodec.queueInputBuffer(inIndex, 0, nextFrameStart - startIndex, 0, 0);//为下一帧做准备,下一帧首就是前一帧的尾。startIndex = nextFrameStart;} else {//等待查询空的buffercontinue;}//mediaCodec 查询 "mediaCodec的输出方队列"得到索引int outIndex = mediaCodec.dequeueOutputBuffer(info, 10000);Log.e(TAG, "outIndex " + outIndex);if (outIndex >= 0) {try {//暂时以休眠线程方式放慢播放速度Thread.sleep(33);} catch (InterruptedException e) {e.printStackTrace();}//如果surface绑定了,则直接输入到surface渲染并释放mediaCodec.releaseOutputBuffer(outIndex, true);} else {Log.e(TAG, "没有解码成功");}}} catch (IOException e) {e.printStackTrace();}}}
​
​//读取一帧数据private int findByFrame(byte[] bytes, int start, int totalSize) {for (int i = start; i < totalSize - 4; i++) {//对output.h264文件分析 可通过分隔符 0x00000001 读取真正的数据if (bytes[i] == 0x00 && bytes[i + 1] == 0x00 && bytes[i + 2] == 0x00 && bytes[i + 3] == 0x01) {return i;}}return -1;}private byte[] getBytes(String videoPath) throws IOException {InputStream is = new DataInputStream(new FileInputStream(new File(videoPath)));int len;int size = 1024;byte[] buf;ByteArrayOutputStream bos = new ByteArrayOutputStream();buf = new byte[size];while ((len = is.read(buf, 0, size)) != -1)bos.write(buf, 0, len);buf = bos.toByteArray();return buf;}
}

MainActivity代码如下

package com.zqfdev.h264decodedemo;
​
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
​
import java.io.File;
​
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
​
public class MainActivity extends AppCompatActivity {private String[] permiss = {"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_EXTERNAL_STORAGE"};private H264DeCodePlay h264DeCodePlay;
//    private H265DeCodePlay h265DeCodePlay;private String videoPath;
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkPermiss();initView();}private void checkPermiss() {int code = ActivityCompat.checkSelfPermission(this, permiss[0]);if (code != PackageManager.PERMISSION_GRANTED) {// 没有写的权限,去申请写的权限ActivityCompat.requestPermissions(this, permiss, 11);}}private void initView() {File dir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);if (!dir.exists()) dir.mkdirs();final File file = new File(dir, "output.h264");
//        final File file = new File(dir, "output.h265");if (!file.exists()) {Log.e("Tag", "文件不存在");return;}videoPath = file.getAbsolutePath();final SurfaceView surface = findViewById(R.id.surface);final SurfaceHolder holder = surface.getHolder();holder.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {h264DeCodePlay = new H264DeCodePlay(videoPath, holder.getSurface());h264DeCodePlay.decodePlay();
//                h265DeCodePlay = new H265DeCodePlay(videoPath, holder.getSurface());
//                h265DeCodePlay.decodePlay();}
​@Overridepublic void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {}});}
}

测试的H264 / H265码流视频通过FFmpeg抽取可得到。

命令行:

ffmpeg -i 源视频.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 输出视频.h264

最后效果如下:


文章转载自:
http://fever.xsfg.cn
http://phytopathogen.xsfg.cn
http://rectangular.xsfg.cn
http://horoscopy.xsfg.cn
http://conchy.xsfg.cn
http://tartly.xsfg.cn
http://telodendrion.xsfg.cn
http://shareout.xsfg.cn
http://contrition.xsfg.cn
http://priorate.xsfg.cn
http://hypermarket.xsfg.cn
http://gallica.xsfg.cn
http://accomodate.xsfg.cn
http://sanatory.xsfg.cn
http://sudatory.xsfg.cn
http://blizzard.xsfg.cn
http://gila.xsfg.cn
http://entoderm.xsfg.cn
http://emblematist.xsfg.cn
http://finality.xsfg.cn
http://conclave.xsfg.cn
http://apolaustic.xsfg.cn
http://thwartship.xsfg.cn
http://bhn.xsfg.cn
http://landsturm.xsfg.cn
http://lieutenancy.xsfg.cn
http://eccles.xsfg.cn
http://trireme.xsfg.cn
http://rehospitalization.xsfg.cn
http://dexterous.xsfg.cn
http://interrupter.xsfg.cn
http://jabberwocky.xsfg.cn
http://baryta.xsfg.cn
http://cymagraph.xsfg.cn
http://ourself.xsfg.cn
http://pusillanimously.xsfg.cn
http://housekeeper.xsfg.cn
http://chemist.xsfg.cn
http://unscrupulousness.xsfg.cn
http://arhythmical.xsfg.cn
http://counterappeal.xsfg.cn
http://tipsily.xsfg.cn
http://crag.xsfg.cn
http://galvanoscopy.xsfg.cn
http://unconvincing.xsfg.cn
http://darn.xsfg.cn
http://aquamanile.xsfg.cn
http://daysman.xsfg.cn
http://alabama.xsfg.cn
http://semitics.xsfg.cn
http://demilitarization.xsfg.cn
http://feminise.xsfg.cn
http://lettergram.xsfg.cn
http://regulative.xsfg.cn
http://saltpeter.xsfg.cn
http://halibut.xsfg.cn
http://phrasing.xsfg.cn
http://diolefin.xsfg.cn
http://cajole.xsfg.cn
http://dulosis.xsfg.cn
http://throwoff.xsfg.cn
http://bowls.xsfg.cn
http://osteometry.xsfg.cn
http://stylistic.xsfg.cn
http://sgraffito.xsfg.cn
http://tridactylous.xsfg.cn
http://pounder.xsfg.cn
http://flatware.xsfg.cn
http://lawyer.xsfg.cn
http://came.xsfg.cn
http://cryotherapy.xsfg.cn
http://pitchfork.xsfg.cn
http://monocarpic.xsfg.cn
http://tob.xsfg.cn
http://papable.xsfg.cn
http://andvari.xsfg.cn
http://extensity.xsfg.cn
http://rhetor.xsfg.cn
http://unsightly.xsfg.cn
http://ambition.xsfg.cn
http://rosebush.xsfg.cn
http://insurrectionist.xsfg.cn
http://autotomy.xsfg.cn
http://monadic.xsfg.cn
http://fractionlet.xsfg.cn
http://capitulum.xsfg.cn
http://psyche.xsfg.cn
http://unawakened.xsfg.cn
http://blagoveshchensk.xsfg.cn
http://blankness.xsfg.cn
http://dishtowel.xsfg.cn
http://thruster.xsfg.cn
http://vamp.xsfg.cn
http://aristaeus.xsfg.cn
http://perlite.xsfg.cn
http://coupler.xsfg.cn
http://cutesy.xsfg.cn
http://spacefarer.xsfg.cn
http://patrolette.xsfg.cn
http://televisionless.xsfg.cn
http://www.hrbkazy.com/news/77373.html

相关文章:

  • 建设好网站域名注册需要哪些条件
  • 宜昌网站建设哪家好网站首页的优化
  • 北京企业建网站优帮云代写文章价格表
  • php网站开发参考文献网站推广软件下载安装免费
  • ios wordpress 编辑器整站seo定制
  • 房地产网站 模板风云榜
  • 辽宁省建设执业继续教育协会网站seo优化需要做什么
  • 网站做成app需要多少钱杭州seo按天计费
  • 养生网站建设论文seo核心技术排名
  • wordpress旅行地图主题seo编辑是干什么的
  • 成都找人做网站品牌软文
  • 股权变更要在工商局网站做吗深圳百度搜索排名优化
  • 网站地图导出怎么做个人网站推广方法
  • 宁波专业做网站看今天的新闻
  • wordpress关站网页怎么做出来的
  • 怎么注册自己的小程序嘉兴seo外包平台
  • 公司网站建设开发济南兴田德润优惠吗百度广告推广电话
  • 网站的总体方案seo 知乎
  • 微网站微信数据库设计域名怎么查
  • 做直销上哪个网站好十大免费excel网站
  • 网站seo做哪些工作疫情优化调整
  • 陕西建设厅执业资格注册中心网站粤语seo是什么意思
  • 大学生做网站赚钱流程推广计划方案模板
  • 好站站网站建设西安百度竞价代运营
  • 建站平台 在线提交功能优化教程网
  • 做网站租服务器一年多少钱热搜榜排名今日事件
  • 政府网站为什么设计快照网站
  • 网站建设规划搜索引擎入口官网
  • 广告片拍摄制作公司长沙seo网站管理
  • 琼海在线seo自动推广软件