谁能帮我详细解释一下Android MediaCodec类中queueInputBuffer这个方法
queueInputBuffer和dequeueInputBuffer是一对方法,两个要在一起使用哦。
首先,这一对函数的应用场合是对输入的数据流进行编码或者解码处理的时候,你会通过各种方法获得一个ByteBuffer的数组,这些数据就是准备处理的数据。
你要通过自己的方法找到你要处理的部分,然后调用dequeueInputBuffer方法提取出要处理的部分(也就是一个ByteBuffer数据流),把这一部分放到缓存区。
接下来就是你自己对于这个数据流的处理了。
然后在处理完毕之后,一定要调用queueInputBuffer把这个ByteBuffer放回到队列中,这样才能正确释放缓存区。
对于输出的数据流,同样也有一对这样的函数,叫做queueOutputBuffer和dequeueOutputBuffer,作用类似哦。
希望采纳~w
android mediacodec有什么方法
Android 用MediaCodec实现视频硬解码
本文向你讲述如何用android标准的API (MediaCodec)实现视频的硬件编解码。例程将从摄像头采集视频开始,然后进行H264编码,再解码,然后显示。我将尽量讲得简短而清晰,不展示那些不相关的代码。但是,我不建议你读这篇文章,也不建议你开发这类应用,而应该转而开发一些戳鱼、打鸟、其乐融融的程序。好吧,下面的内容是写给那些执迷不悟的人的,看完之后也许你会同意我的说法:Android只是一个玩具,很难指望它来做靠谱的应用。
1、从摄像头采集视频
可以通过摄像头Preview的回调,来获取视频数据。
首先创建摄像头,并设置参数:
[java] view plaincopy
cam = Camera.open();
cam.setPreviewDisplay(holder);
Camera.Parameters parameters = cam.getParameters();
parameters.setFlashMode("off"); // 无闪光灯
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
parameters.setPreviewFormat(ImageFormat.YV12);
parameters.setPictureSize(camWidth, camHeight);
parameters.setPreviewSize(camWidth, camHeight);
//这两个属性 如果这两个属性设置的和真实手机的不一样时,就会报错
cam.setParameters(parameters);
宽度和高度必须是摄像头支持的尺寸,否则会报错。要获得所有支持的尺寸,可用getSupportedPreviewSizes,这里不再累述。据说所有的参数必须设全,漏掉一个就可能报错,不过只是据说,我只设了几个属性也没出错。 然后就开始Preview了:
[java] view plaincopy
buf = new byte[camWidth * camHeight * 3 / 2];
cam.addCallbackBuffer(buf);
cam.setPreviewCallbackWithBuffer(this);
cam.startPreview();
setPreviewCallbackWithBuffer是很有必要的,不然每次回调系统都重新分配缓冲区,效率会很低。
在onPreviewFrame中就可以获得原始的图片了(当然,this 肯定要 implements PreviewCallback了)。这里我们是把它传给编码器:
[java] view plaincopy
public void onPreviewFrame(byte[] data, Camera camera) {
if (frameListener != null) {
frameListener.onFrame(data, 0, data.length, 0);
}
cam.addCallbackBuffer(buf);
}
2、编码
首先要初始化编码器:
[java] view plaincopy
mediaCodec = MediaCodec.createEncoderByType("Video/AVC");
MediaFormat mediaFormat = MediaFormat.createVideoFormat(type, width, height);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
然后就是给他喂数据了,这里的数据是来自摄像头的:
[java] view plaincopy
public void onFrame(byte[] buf, int offset, int length, int flag) {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buf, offset, length);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
if (frameListener != null)
frameListener.onFrame(outputBuffer, 0, length, flag);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
}
先把来自摄像头的数据喂给它,然后从它里面取压缩好的数据喂给解码器。
3、解码和显示
首先初始化解码器:
[java] view plaincopy
mediaCodec = MediaCodec.createDecoderByType("Video/AVC");
MediaFormat mediaFormat = MediaFormat.createVideoFormat(mime, width, height);
mediaCodec.configure(mediaFormat, surface, null, 0);
mediaCodec.start();
这里通过给解码器一个surface,解码器就能直接显示画面。
然后就是处理数据了:
[java] view plaincopy
public void onFrame(byte[] buf, int offset, int length, int flag) {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buf, offset, length);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, length, mCount * 1000000 / FRAME_RATE, 0);
mCount++;
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);
while (outputBufferIndex >= 0) {
mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
}
}
queueInputBuffer第三个参数是时间戳,其实怎么写都无所谓,只要是按时间线性增加的就可以,这里就随便弄一个了。后面一段的代码就是把缓冲区给释放掉,因为我们直接让解码器显示,就不需要解码出来的数据了,但是必须要这么释放一下,否则解码器始终给你留着,内存就该不够用了。
好了,到现在,基本上就可以了。如果你运气够好,现在就能看到视频了,比如在我的三星手机上这样就可以了。但是,我试过几个其他平台,多数都不可以,总是有各种各样的问题,如果要开发一个不依赖平台的应用,还有很多的问题要解决。说说我遇到的一些情况:
1、视频尺寸
一般都能支持176X144/352X288这种尺寸,但是大一些的,640X480就有很多机子不行了,至于为什么,我也不知道。当然,这个尺寸必须和摄像头预览的尺寸一致,预览的尺寸可以枚举一下。
2、颜色空间
根据ANdroid SDK文档,确保所有硬件平台都支持的颜色,在摄像头预览输出是YUV12,在编码器输入是COLOR_FormatYUV420Planar,也就是前面代码中设置的那样。 不过,文档终究是文档,否则安卓就不是安卓。
在有的平台上,这两个颜色格式是一样的,摄像头的输出可以直接作为编码器的输入。也有的平台,两个是不一样的,前者就是YUV12,后者等于I420,需要把前者的UV分量颠倒一下。下面的代码效率不高,可供参考。
[java] view plaincopy
byte[] i420bytes = null;
private byte[] swapYV12toI420(byte[] yv12bytes, int width, int height) {
if (i420bytes == null)
i420bytes = new byte[yv12bytes.length];
for (int i = 0; i < width*height; i++)
i420bytes[i] = yv12bytes[i];
for (int i = width*height; i < width*height + (width/2*height/2); i++)
i420bytes[i] = yv12bytes[i + (width/2*height/2)];
for (int i = width*height + (width/2*height/2); i < width*height + 2*(width/2*height/2); i++)
i420bytes[i] = yv12bytes[i - (width/2*height/2)];
return i420bytes;
}
这里的困难是,我不知道怎样去判断是否需要这个转换。据说,Android 4.3不用再从摄像头的PreView里面取图像,避开了这个问题。这里有个例子,虽然我没读,但看起来挺厉害的样子,应该不会有错吧(觉厉应然)。http://bigflake.com/mediacodec/CameraToMpegTest.java.txt
3、输入输出缓冲区的格式
SDK里并没有规定格式,但是,这种情况H264的格式基本上就是附录B。但是,也有比较有特色的,它就是不带那个StartCode,就是那个0x000001,搞得把他编码器编出来的东西送给他的解码器,他自己都解不出来。还好,我们可以自己加。
[java] view plaincopy
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size + 3];
outputBuffer.get(outData, 3, bufferInfo.size);
if (frameListener != null) {
if ((outData[3]==0 && outData[4]==0 && outData[5]==1)
|| (outData[3]==0 && outData[4]==0 && outData[5]==0 && outData[6]==1))
{
frameListener.onFrame(outData, 3, outData.length-3, bufferInfo.flags);
}
else
{
outData[0] = 0;
outData[1] = 0;
outData[2] = 1;
frameListener.onFrame(outData, 0, outData.length, bufferInfo.flags);
}
}
4、有时候会死在dequeueInputBuffer(-1)上面
根据SDK文档,dequeueInputBuffer 的参数表示等待的时间(毫秒),-1表示一直等,0表示不等。按常理传-1就行,但实际上在很多机子上会挂掉,没办法,还是传0吧,丢帧总比挂掉好。当然也可以传一个具体的毫秒数,不过没什么大意思吧。
谁能帮我翻译一下这篇文章(翻成英语)
Three different units of measurement of the ecological footprint method
- A town in Shandong Province as an example胡官屯
Abstract: The sustainable development of small cities and towns has always been the focus of our country. In this paper, the ecological footprint theory and method has been applied to small town environmental planning study, in different units of measurement to establish the ecological footprint model for the ecological deficit per capita income to reflect the economic activities of small cities and towns on natural ecosystems caused by the pressure and damage . PHA method for per capita ecological deficit -0.230240 hm2 / person than GHA nha law law and ecological deficit per capita income more in line with the ecological status of the town of胡官屯. More suitable for the Act by the arable land, grassland equilibrium factor, output factor, the impact of the larger small towns ecological footprint calculations.
Key words: ecological footprint; small towns; environmental planning
1 Introduction
In recent years, with the small town population, the scale of construction continues to expand, small cities and towns of their socio-economic activities will inevitably cause great damage to the ecosystem. To protect the sustainability of the development of small towns, it is necessary to enable mankind to the small towns of the pressure on natural systems in the scope of the bearing capacity of the ecosystem, it can not jeopardize the safety of its ecosystem, therefore, small cities and towns have implemented environmental planning must be scientific and rational, Be sure to describe the measure from various angles of human activities on ecosystems caused by the pressure and influence.
2, Ecological Footprint Analysis
Ecological footprint analysis as a measure of human demand for natural resources and the extent of available natural resources to human life support services to the gap between the measure as a standard measure of human activities on natural ecosystems of coercion. Calculation of ecological footprint methodology is simple, easy to comparative analysis of cause for concern. After years of development and improvement, practical application and amended several times [1-11], this method has developed into a sustained continuity planning tool, has been widely used in the global multi-scale multi-scale studies.
Ecological Footprint analysis is by the Canadian ecological economist William and his doctoral Wackernagel in the early 90s put forward in 1999, was introduced in our country. In spatial scale, our country of a region of ecological footprint analysis is usually the use of global hectares (gha), hectares of country [10] (nha), the provincial hectares [11] (pha) for the unit of measurement to establish the ecological footprint of the model to calculation.
3,胡官屯the town as an example to calculate the ecological footprint
Shandong Province is located in the most economically developed country in east China plains northwest of the northern part of Shandong, transport facilitation.胡官屯town is the capital city an important component of the circle, with east and west, north and south access to the macro-geographic conditions. In recent years, the town of胡官屯socio-economic and the ecological environment has been rapid development has made remarkable achievements.胡官屯the town as an example to discuss the analysis of gha, nha and PHA and the similarities and differences of three methods to identify small towns of China's Shandong Province, environmental planning approach. Used gha, nha and PHA method胡官屯town of Ecological Footprint results shown in Table 1, Table 2, Table 3.
live与live in的区别
其实就是分析成分的问题 第一个划线的to live是作状语 第二个是作定语 它们之间有很大的区别 作状语就直接用to do 不用考虑带不带介词的问题 但是作定语就要想到是否带介词的问题 比如说 I have a pen to write 这就错了 应该加一个with 怎么理解呢 你将句子倒过来 I write with a pen 这就对了 如果不加with 就是I write a pen 我写笔吗? 相反 如果是I use a pen to write 就对了 为什么呢 因为to write 做目的状语 我用笔 用笔的目的是写 所以你一定要好好想想 将它们的区别分开 这些都不常考的 不是特别重要 以后你慢慢会懂的
live和live in的区别
to live in它们所修饰的名词实际上和它们构成了动宾关系,比如说a house to live in中,live in 和house 就是动宾关系,house 是live in 的宾语,放到后面就是live in the house。因为live是不及物动词,必须得和动词搭配才能加宾语,因此必须有in。
例:1.I have a room to live in.我有一间房子住.
可变为:I live in a room.(如果去掉介词in,句子明显不通.因为live为不及物动词)
一般来讲,动词不定式作定语时,并且动词不定式与名词之间的关系存在被动关系或者成为动宾关系,如果这个动词是一个不及物动词的话,要在动词后面加上一个介词或副词。
比如。He has no house to live in.
但如果这个名词是place的话,那么就不用介词。http://zhidao.baidu.com/question/165958960.html?an=0&si=2