Android硬编解码工具MediaCodec解析——从猪肉餐馆的故事讲起(三)

持续创造,加快成长!这是我参与「日新方案 6 月更文挑战」的第3天,点击检查活动详情

更多博文,请看音视频系统学习的浪漫马车之总目录

实践项目: 介绍一个自己刚出炉的安卓音视频播工作流程图映录制开源项初始化

视频理论基础:
视频基础知识扫盲
音视频开发基础知识之YUV色彩编码
解析H264视频编码原理—工作流程图制作方法—从孙艺珍的电影说起(一)
解析H264视频编码原理——从孙艺珍的电影说起(二)
H264码流结构一探究竟

Android渠道工作流MediaCodec系列:
Android硬编解码利器MediaCodec解析——从猪肉饭馆的故事讲起(一)
Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(二)
Android硬编解码东西Me初始化游戏启动器失败diaCodec解析——从猪肉饭馆的故事讲起(三)

上篇回忆

前面两篇文章Android硬编解码利器MediaCodec解析——从猪肉饭馆的故事讲起(一)和 Ajava模拟器ndroid硬编解码东工作流程西MediaCodec解析——从猪肉饭馆的故事讲起(二)现已从猪肉饭馆的故事带各位比较详细地阐初始化英文述了Android渠道硬解码东西MediaCodjava是什么意思ec的工作流程和详细的代码,可是前两篇文章的剖析是谷歌浏览器下载基于静态的,可是谷歌账号MediaCodec详细谷歌商店的解码流程是怎么样的,咱们并不知道。java模拟器那么今日就让java编译器代码“动起来”,经过log和辅助代码工作流引擎去愈加深入把握MediaCojava培训dec的解码流程

假如还没看过前面两篇博文,仍是主张看一下,由于本文和前两篇是有很大关联的。

代码运行log剖析

首要点击榜首个item:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

进入到这个界面:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

看下此刻的Log:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

log打印方位在com.android.grafika.PlayMovieActivity,主要看下“SurfaceTexture ready宫颈癌 (984×1384)”这一行:

@Override
public void onSurfaceTextureAvailable(SurfaceTexture st, int width, int height) {
    // There's a short delay between the start of the activity and the initialization
    // of the SurfaceTexture that backs the TextureView.  We don't want to try to
    // send a video stream to the TextureView before it has initialized, so we disable
    // the "play" button until this callback fires.
    Log.d(TAG, "SurfaceTexture ready (" + width + "x" + height + ")");
    mSurfaceTextureReady = true;
    updateControls();
}

还记得Android工作流是什么意思硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(二)画的全体流程图么:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

ojava是什么意思nSurfaceTextureAvailable这个回调办法便是告知咱们,TextureView的SurfaceTexture现已初始化好了,能够开端烘托了。此初始化电脑时出现问题未进行更改刻才会将播映按钮置为可点击。log“Sur工作流程表格模板faceTexture初始化是什么意思 ready (984×13初始化sdk什么意思84)” 中的“(984×1384)”即为TextureView的尺寸。

初始化sdk什么意思刻,悄悄点击播映按钮,所以视频开端动起来了,可谓是络绎时刻旳画面的钟,从反方向开端移动~:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

首要输出了这条log:

D/fuyao-Grafika: Extractor selected track 0 (video/avc): {track-id=1, level=32, mime=vi工作流程表格模板deo/avc, profile=1, language=“` , color-standard=4, display-width=320, csd-1=java.njava环境变量配置io.HeapBy初始化磁盘teBuffer[pos=0 lim=8 cap=8], color-transfer=3, dura工作流程图模板样式tionUs=2033333, display-height=240, width=320, color-range=2, ma工作流x-input-size=383, frame-rate=16,初始化电脑 height=240, csd-0=java.nio.HeapByteBuff工资超过5000怎么扣税er[pos=0 lim=38 cap=38]}

它是在MediaExtractor选中媒体轨迹的时分打印的,打印出详细当时视频轨迹格局相关信息:

/**
 * Selects the video track, if any.
 *
 * @return the track index, or -1 if no video track is found.
 */
private static int selectTrack(MediaExtractor extractor) {
    // Select the first video track we find, ignore the rest.
    //当时媒体文件共有多少个轨迹(视频轨迹、音频轨迹、字幕轨迹等等)
    int numTracks = extractor.getTrackCount();
    for (int i = 0; i < numTracks; i++) {
        //第i个轨迹的MediaFormat
        MediaFormat format = extractor.getTrackFormat(i);
        //format对应的mime类型
        String mime = format.getString(MediaFormat.KEY_MIME);
        //找到视频轨迹的index
        if (mime.startsWith("video/")) {
            if (VERBOSE) {
            //留意这行的log打印
                Log.d(TAG, "Extractor selected track " + i + " (" + mime + "): " + format);
            }
            return i;
        }
    }
    return -1;
}

略微解说下log中的几个要害参数:

1.log中的levejava培训l和profile指的是画质等级,以下解说引证于# H264编码profile & level操控

H.26谷歌三件套4有四种画质等级,分别是工作流程组织baseline, extended, main, hi初始化磁盘gh:
1、Bjava环境变量配置aseline Profile:基本画质。支撑I/P 帧,只支撑无交织(Prjava语言ogressive)和CAVLC;
2、Extended profile:进阶画质。支撑I/P/B/SP/SI 帧公积金,只支撑无交织(Pr谷歌三件套ogressive)和CAVLC;(用的少)
3、Main profile:主流画工作流程质。提供I/P/谷歌账号B 帧,支撑无交织(Progressive)和交织(Interlaced),
也支撑CAVLC 和CABAC 的支撑;
4、High projava环境变量配置file:高档画质。在main Profi初始化sdk什么意思le 的基础上增加了8×8内部预测、自定义量化、 无损视频编码和更多的YUV 格局;
H.264 B工作流程怎么写aseline profile、Extended profile和Main profile都是针对工作流程图模板样式8位样本数据、4:2:0格局(YUV)的视频序列。在相同装备情况下,High profile(HP)能够比Main profile(MP)下降10%的码率。
依据应用范畴的不同,Baseline profile多应用于谷歌三件套公司让员工下班发手机电量截图时通讯范畴,Main profile多应用于流媒体范畴,High profile则多应用于广电和存储范畴。

2.mime为vide初始化英文o/avc,这个上篇文章现已讲过,video/avc即为H264。

3.co初始化电脑lor-standard:指的是视频的色彩格局,谷歌浏览器

/**
 * An optional key describing the color primaries, white point and
 * luminance factors for video content.
 *
 * The associated value is an integer: 0 if unspecified, or one of the
 * COLOR_STANDARD_ values.
 */
public static final String KEY_COLOR_STANDARD = "color-standard";
/** BT.709 color chromacity coordinates with KR = 0.2126, KB = 0.0722. */
public static final int COLOR_STANDARD_BT709 = 1;
/** BT.601 625 color chromacity coordinates with KR = 0.299, KB = 0.114. */
public static final int COLOR_STANDARD_BT601_PAL = 2;
/** BT.601 525 color chromacity coordinates with KR = 0.299, KB = 0.114. */
public static final int COLOR_STANDARD_BT601_NTSC = 4;
/** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
public static final int COLOR_STANDARD_BT2020 = 6;

还记得# 音视频开发基础知识之YUV色彩谷歌地图编码 里边说过,RGB到YUV有不同的转化规范:

现在一般解码后的视频格局为yuv,可是一般java怎么读显卡烘托的格局是RGB,所以需求把yuv转化为RGB。

这儿触及到 Color Range 这个概念。Color Range 分为两种,一种是 Full Range,一种是 Limited RangeFull Range 的 R、G、B 取值规模都是 0~255。而 Limited Range 的 R、G、B 取值规模是 16~235。

关于每种Color Range来说,还有不同的转初始化电脑换规范,常见的规范主要是 BT601 和 BT709java语言BT601 是标清的规范,而 BT709 是高清的规范)。

这儿该视频的color-sta工作流是什么意思ndajava模拟器rd为谷歌浏览器下载4,即转换规范为java面试题BT.601 525。

4.color-range: 上面引证部分现已提及,当时color-rangejava怎么读为2,看龚俊谷歌文档的常量值说明:

/** Limited range. Y component values range from 16 to 235 for 8-bit content.
 *  Cr, Cy values range from 16 to 240 for 8-bit content.
 *  This is the default for video content. */
public static final int COLOR_RANGE_LIMITED = 2;
/** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
public static final int COLOR_RANGE_FULL = 1;

所以当时视宫颈癌频的color-range为Limi工资超过5000怎么扣税ted range。

其他参数由于数量太多谷歌地图,咱们也大部分能工作流程图够看理解,就不一一解说了。

看接下来的log:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

榜首行是这儿打印的:

//拿到可用的ByteBuffer的index
int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
//依据index得到对应的输入ByteBuffer
ByteBuffer inputBuf = decoderInputBuffers[inputBufIndex];
Log.d(TAG, "decoderInputBuffers inputBuf:" + inputBuf + ",inputBufIndex:" + inputBufIndex);

打印的是inputBuffer的情况,上一篇工作流现已讲过,这儿就如同生猪肉采购员问询厨师有没有空篮子,厨师在TIMEOUT_USEC微秒时刻内告知了采购员篮子的编号,然后采购员依据编号找到对应的空篮子。java培训

依据log能够看出:

decoderInpu工作流是什么意思tBuffers inputBu公积金f:java.nio.DirectByt工作流程组织eBuffer[pos=0 lim=6291456 cap=6291456],inputBufIndex:2

这个空Buffer巨细为java面试题6291456字节(pos表明当时操作指针指向的方位,lim表明当时可读或者可写宫颈癌的最大数量,cap表明其容量),igooglenputBufIndex为2,初始化失败是怎么解决即该Buffer在MediaCodec的输入Buffer数组的方位是2。

submitted frame 0 to dec, size=339

这个log的frame 0表明MediaExtractor的readSam工资超过5000怎么扣税pleData读取出来的第几块数据,在这儿便是第几帧,size=339表明该帧巨细为339字节,当然这是压缩的数据巨细。

下面一条log输出端取数工作流程图据的,即顾客问询厨师猪肉炒好了没有:

D/fuyao-Grafika: dejava语言queueOutputBuffer decoderBufferIndex:-1,mBuffer工资超过5000怎么扣税Info:android.media.MediaCodec$BufferInfo@fcbc6e2

D/fuyao-Grafika: no output from decoder avai工资超过5000怎么扣税lable

这条log来历:

int outputBufferIndex = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
Log.d(TAG, "dequeueOutputBuffer decoderBufferIndex:" + outputBufferIndex + ",mBufferInfo:" + mBufferInfo);

decoderBufferI谷歌浏览器下载ndex为-1,则等于MediaCodec.INFO_TRY_AGAIN_LATER,即当时输出端还没有数据,即厨师告知顾客,猪肉还没做好。

假如看过之前我写的解析HJava264视频编码原理——从孙艺珍的电影说起(一)和 解析H264视频编码原理——从孙艺珍的电影说起(二),就知谷歌play道视频编码是一个非常复杂的过程,触及初始化大量的数学算法,所以解码也不会简略,谷歌空间基本不会刚放一帧数据到input端,output端就立马拿到解码后的初始化英文数据。

从后边的log能够看到,经过很多次在input端放入数据,又测验在output端取出数据的循环之后,终于在榜首次在input端放入数据的77ms秒之后,在output端拿到了数据:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

sta初始化电脑的后果rtup lag是官方demo现已有的统计从榜首次在input端放入数据到榜首次从output端拿到数据的时刻长。

接下来便是取到详细数据的log:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

decoderBujava怎么读ff初始化电脑时出现问题erIndex为0,即取到的解码数据所在的buffer在output端buffer数组第0个。

ecoderOut工作流程putB谷歌商店ufferjava编译器s.length:谷歌安装器8是我专门把output数组数量打印出来:

ByteBuffer[] decoderOutputBuffers = decoder.getOutputBuffers();
Log.d(TAG, "ecoderOutputBuffers.length:" + decoderOutputBuffers.length);

可见output端buffer数组巨细为8个(经过实践发现,该初始化sdk什么意思数值并不是固定的)。

outputBuffer:java.nio.DirectByteBuffer[pos=0 lim=115200 cap=115200]表明该buffer的可用数据和容量都为115200。后边解码出来的数据也是这个巨细,由java模拟器于解码之后的数据便是一帧画面的yuv数据,由于画面的分辨初始化英文率固定,yuv格局也是固定,所以巨细自然也是一样的。

而在output拿到数据之前的上一次取数据的log需求留意下:

D/fuyao-Grafika:dequeueOutputBuffer decoderBufferIndex:-2,mBufferInfo:初始化电脑时出现问题android.media.MediaCodec$Buffer宫颈癌Info@9bec00c

D/fuyao-GrJavaafika: decoder output format cha工作流程模板nged: {crop-right=319, color-format=21, slice-height=240, image-data=java.nio.H谷歌地图eapByteBuffer[pos=0 lim=104 cap=104], mime=video/raw, stride=320, color-standard=4, color-transfer=3, crop-bottom=239, crop-left=0, width=320, color-range=2, crop-t谷歌op=0, height=240}

decoderBufferIndex为2,即MediaCodec.INF初始化电脑的后果O_OUTPUT_FORMAT_CHANGED。在拿到数据之后,会现有一个告知输出数据格java编译器局变化的告知,咱们能够在这儿拿到输出数据的格局。

1.crop谷歌安装器-left=0,crop-right=319,crop谷歌-top=0,cro工资超过5000怎么扣税p-bottom=239表明的是真实的视频区域枸杞的4个顶点在整个视频帧的公司让员工下班发手机电量截图坐标方位。

有读者可能会问,视频不是充满一帧java模拟器么?其实不是的,看下官网的解读 develo工作流是什么意思pe谷歌浏览器r.andrjava模拟器oid.google.cn/reference/a… :

TheMediaForm初始化磁盘at#KEY_WIDTHandMediaFormat#KEY_HEIGHTkeys specify the size o龚俊f工作流程组织 the vjava培训ideo工作流是什么意思 frames; however, for most encondingjava模拟器s t初始化失败是怎么解决he vide公积金o (picture) only occupies a portion of the video frame. This is represented by the ‘crop rectangle’.

You初始化sdk什么意思 need to use the following keys to get the crop rectangle of raw output images from thejava环境变量配置output format. If these keys are not present工作流程图, the video occupies the entire video fr谷歌翻译ame.The crop rectangle is understood in the context of the output framebeforeapplying anyrot谷歌ation.

详细key的含义:

Format KeyTypeDescription
MediaFormat#KEY_CGoROP_LEFTIntegerThe left-coordinate (x) of the crop rectangle
MediaFormat初始化英文#KEY_CROP_TOPIntegerThe tjava面试题op-coordinate (y) of the crop rectangle
MediaFormat#KEjava培训Y_CROP_RIGHTIntegerThe right-coord初始化inate (x)MINUS 1of thejavaee crop rectangle
MediaFormat#KEY_CROP_BOTTOMIntegerThe bottom-coordinate (y)MINUS 1of the crop rectangle

官网又给了一段经过这4个值计算视频有效区域的代码:

MediaFormat format = decoder.getOutputFormat(…);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
if (format.containsKey(MediaFormat.KEY_CROP_LEFT)
    && format.containsKey(MediaFormat.KEY_CROP_RIGHT)) {
  width = format.getInteger(MediaFormat.KEY_CROP_RIGHT) + 1
        - format.getInteger(MediaFormat.KEY_CROP_LEFT);
}
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
if (format.containsKey(MediaFormat.KEY_CROP_TOP)
    && format.containsKey(MediaFormat.KEY_CROP_BOTTOM)) {
  height = format.getInteger(MediaFormat.KEY_CROP_BOTTOM) + 1
        - format.getInteger(MediaFormat.KEY_CROP_TOP);
}

2.color-format:色彩编码格局。21即为COLOR_FormatYUV420SemiPla工作流程图制作方法nar,也常叫做叫作NV21。关于yuv详细格局在音视频开发公司让员工下班发手机电量截图基础知识之YUV色彩编码 已有叙说,不过文章并没有详细讲NV21,NV21的于半平面格局(semi plannjava是什么意思er),y独立放一个数组,uv放一个数组,先V后工资超过5000怎么扣税U交织存放(图来工龄越长退休金越多吗自: 浅析 YUV 色彩空间)

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)
比方一个4*4的画面,散布如下图所示:

  1. Y Y Y Y

  2. Y Y Y Y

  3. Y Y Y Y

  4. Y Y Y Y

  5. V U V U

  6. V U V U

3.slice-height:指的是帧的高公积金度,即有多少行,不过这个java是什么意思行数可能是内存对齐过的,有时分为了进步读取速度,视频帧高度会填充到2的次幂数值。

4.st谷歌商店ride:跨距,是图画存储的时分有的一个概念。它指的是图画存储时内存中每行像素所占用的空间javaee 同样的,这个也是经过内存对齐的,所以是大于等于原视频的每行像素个数。很多视频花屏问题的初始化电脑根源便是忽略了stride这个特点。

其他参数上面已讲过,就不赘述。

拿到输出的解码数据就经过re工龄差一年工资差多少lea谷歌商店seOutputBuffer烘托到Sgoogleurface:

//将输出buffer数组的第outputBufferIndex个buffer绘制到surface。doRender为true绘制到装备的surface
decoder.releaseOutputBuffer(outputBufferIndex, doRender);

咱们看到log的output最终一帧数据是:

output EOS

当调用:

int outputBufferIndex = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);

得到的mBufferInfo.flags为MediaCodec.BUFFER_FLAG_END_OF_STREAM(intput端在视频最终一帧初始化游戏启动器失败的时分传入)的时分,说明该帧现已是视频最终一帧了,此刻就跳出解码的工龄越长退休金越多吗大循环,准备开释资源:

 finally {
    // release everything we grabbed
    if (decoder != null) {
        //Call stop() to return the codec to the Uninitialized state, whereupon it may be configured again.
        decoder.stop();
        decoder.release();
        decoder = null;
    }
    if (extractor != null) {
        extractor.release();
        extractor = null;
    }
}

还记得Android硬编解码利器MediaCodec解析——从猪肉饭馆的故事讲起(一) 提工作流程表格模板及过得M初始化电脑ediaCodec的状况机么:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

先调用了stop办法,就进java怎么读入了Uninitialized状况,即猪肉饭馆要拾掇桌椅了,拾掇完桌椅之后,再调用release就开释资源,即猪肉饭馆关工作流门了。

将解码输出数据保存下来

接下来来做一件有趣的事情,便是将每次输出的解码数据保存为图片。

创建一个办法接纳输出的一帧数据,然后经过系统提供的YuvImage能够将yuv数据转化为jpeg数据,然后经过BitmapFactory.decodeByteArray将jpeg数据转化为Bitmap,再保存到本地文件工作流程图模板样式夹中。

private void outputFrameAsPic(byte[] ba, int i) {
    Log.d(TAG, "outputBuffer i:" + i);
    YuvImage yuvImage = new YuvImage(ba, ImageFormat.NV21, mVideoWidth, mVideoHeight, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    //将yuv转化为jpeg
    yuvImage.compressToJpeg(new Rect(0, 0, mVideoWidth, mVideoHeight), 100, baos);
    byte[] jdata = baos.toByteArray();//rgb
    Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
    if (bmp != null) {
        try {
            File parent = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/moviePlayer/");
            if (!parent.exists()){
                parent.mkdirs();
            }
            File myCaptureFile = new File(parent.getAbsolutePath(),String.format("img%s.png", i));
            if (!myCaptureFile.exists()){
                myCaptureFile.createNewFile();
            }
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
            bmp.compress(Bitmap.CompressFormat.JPEG, 80, bos);
            Log.d(TAG, "bmp.compress myCaptureFile:" + myCaptureFile.getAbsolutePath());
            bos.flush();
            bos.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "outputFrameAsPic Exception:" + e);
        }
    }
}

然后在每次获得output端Buffer的当地调用该办法:

ByteBuffer outputBuffer = decoderOutputBuffers[outputBufferIndex];
Log.d(TAG, "outputBuffer:" + outputBuffer);
outputBuffer.position(mBufferInfo.offset);
outputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
byte[] ba = new byte[outputBuffer.remaining()];
//byteBuffer数据放入ba
outputBuffer.get(ba);
//输出的一帧保存为本地的一张图片
outputFrameAsPic(ba, decodeFrameIndex);

再运行下程序,得到以下图片:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

可见每一帧都成功截图并保工作流引擎存到本地~~

同步与异步模式

最终说下,MediaCodec编解码是分为同步和异步模式的(Android 5.0开端支撑异步状况),同步便是比方生猪肉采购员和顾客有必要 在Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(二)的关于初始化英文MediaCod工作流程ec的解码流程代码,是属于同步,所谓的同步,是相关于异步而言的。同步和异java语言步最大的不同,个人认为便是前者是要求咱们自动去咨询MeidaCodec有没有可用的Buffer能够用,后者是MeidaCodec来告知咱初始化英文们现已有有了可用的buffer。就像原来是猪肉采购员自动问询厨师有没有空篮子能够用,现在变为厨师发个微信告知采购员现在有空篮子能够用。

关于异步来说,MediaCodec的工作状况和同步有一点不同:

Android硬编解码东西MediaCodec解析——从猪肉饭馆的故事讲起(三)

异步的情况下从Configured会直接进入Running状况,然后等待MediaCodec工龄越长退休金越多吗的回调告知再处理数据即可,以下为官方给的代码模板:

MediaCodec codec = MediaCodec.createByCodecName(name);
MediaFormat mOutputFormat; // member variable
codec.setCallback(new MediaCodec.Callback() {
 @Override
 void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
  ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
  // fill inputBuffer with valid data
  …
  codec.queueInputBuffer(inputBufferId, …);
 }

 @Override
 void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
  ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
  MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
  // bufferFormat is equivalent to mOutputFormat
  // outputBuffer is ready to be processed or rendered.
  …
  codec.releaseOutputBuffer(outputBufferId, …);
 }

 @Override
 void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
  // Subsequent data will conform to new format.
  // Can ignore if using getOutputFormat(outputBufferId)
  mOutputFormat = format; // option B
 }

 @Override
 void onError(…) {
  …
 }
});
codec.configure(format, …);
mOutputFormat = codec.getOutputFormat(); // option B
codec.start();
// wait for processing to complete
codec.stop();
codec.release();

总结

本文在上一文章剖析代码的基础上运行了代码,经过剖析log剖析解码流程的细节,让各位对解码流程有更清晰的认识。并将解码出来的每帧截图保存到本地,工作流程模板验证了视频解码的output端每次获取的数据确实是表宫颈癌明一帧的数据。最终讲了一下MediaCodec编解码异步模式相关。

夸姣的时光总是过得很快,不知不觉现已用了三篇博文讲MediaCGoodec了,剩余的编码部分枸杞其实和解码谷歌账号也差不多,无java环境变量配置非是换个猪肉饭馆哈哈,我有空再写写,由于我现已迫不及待地想进入下一个系列了——OpenGL系列。初始化电脑的后果 由于解码工作流程成功后,便是烘托到屏幕了,而当时Android渠道最主流的烘托东西,便是OpenGL了。

原创不易,假如觉得本文对自己有帮助,别忘了顺手点赞和关注,这也是我创造的最大动力~

发表评论

提供最优质的资源集合

立即查看 了解详情