我写了一个从YUV_420_888到Bitmap的转换,考虑到以下逻辑(据我所知):
总结该方法:内核的坐标x和y与Y平面(2d分配)的非填充部分的x和y以及输出位图的x和y都是一致的.然而,U平面和V平面具有与Y平面不同的结构,因为它们使用1个字节覆盖4个像素,此外,可能具有多于一个的PixelStride,此外它们可能也有一个可以与Y平面不同的填充.因此,为了通过内核有效地访问U和V,我将它们放入1-d分配并创建索引"uvIndex",该索引给出了在给定的1-d分配中相应的U-和V的位置( x,y)坐标(非填充)Y平面(以及输出位图).
为了保持rs-Kernel的精简,我通过LaunchOptions限制x范围来排除yPlane中的填充区域(这反映了y平面的RowStride,因此可以在内核中忽略).所以我们只需要考虑uvIndex中的uvPixelStride和uvRowStride,即用于访问u值和v值的索引.
这是我的代码:
Renderscript内核,名为yuv420888.rs
#pragma version(1)
#pragma rs java_package_name(com.xxxyyy.testcamera2);
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
uint picWidth, uvPixelStride, uvRowStride ;
rs_allocation ypsIn,uIn,vIn;
// The LaunchOptions ensure that the Kernel does not enter the padding zone of Y, so yRowStride can be ignored WITHIN the Kernel.
uchar4 __attribute__((kernel)) doConvert(uint32_t x, uint32_t y) {
// index for accessing the uIn's and vIn's
uint uvIndex= uvPixelStride * (x/2) + uvRowStride*(y/2);
// get the y,u,v values
uchar yps= rsGetElementAt_uchar(ypsIn, x, y);
uchar …
Run Code Online (Sandbox Code Playgroud) 我需要在没有MediaExtractor的情况下使用MediaCodec,我正在使用FileInputStream读取文件.目前它不工作,它在屏幕上显示绿色的乱码图像.
这是完整的源代码:
FileInputStream in = new FileInputStream("/sdcard/sample.ts");
String mimeType = "video/avc";
MediaCodec decoder = MediaCodec.createDecoderByType(mimeType);
MediaFormat format = MediaFormat.createVideoFormat(mimeType, 1920, 1080);
byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 };
byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 };
format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
format.setInteger("durationUs", 63446722); …
Run Code Online (Sandbox Code Playgroud) 我有一个固定宽度和高度的TextureView,我想在其中显示相机预览.我需要裁剪相机预览,以便它看起来不会在我的TextureView中拉伸.怎么做种植?如果我需要使用OpenGL,如何将Surface Texture绑定到OpenGL以及如何使用OpenGL进行裁剪?
public class MyActivity extends Activity implements TextureView.SurfaceTextureListener
{
private Camera mCamera;
private TextureView mTextureView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_options);
mTextureView = (TextureView) findViewById(R.id.camera_preview);
mTextureView.setSurfaceTextureListener(this);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
try
{
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch (IOException ioe) {
// Something bad happened
}
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
} …
Run Code Online (Sandbox Code Playgroud) 我使用MediaCodec
Android SDK提供的类,因为API级别16与OMX.SEC.aac.enc
编码器一起将音频编码为文件.我从AudioRecord
课堂上得到了音频输入.我的AudioRecord
类实例配置如下:
bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_DEFAULT, bufferSize);
Run Code Online (Sandbox Code Playgroud)
我能够从AudioRecord
实例播放原始数据,因此问题不在那里.
我将AudioRecord
实例的输出写入ByteBuffer
实例并将其传递给编码器的可用输入缓冲区.编码器的输出被写入SD卡上的文件.
这些是我的MediaCodec
实例的配置参数:
codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Run Code Online (Sandbox Code Playgroud)
VLC告诉我,我的aac文件中没有流.该命令FFMPEG -i @filename@
给出了以下错误:处理输入时找到无效数据.我测试过的所有媒体播放器都无法播放我的文件.
为什么我无法播放我的文件?我没有收到OpenMAX
错误,LogCat
应用程序在编码时不会崩溃.我写了一个视频编码器,它的工作原理与之相同.
这是将数据从AudioRecord
实例读取到缓冲区的代码:
new Thread() {
public void run() { …
Run Code Online (Sandbox Code Playgroud) 我在Android应用程序中遇到了一个非常奇怪的问题.在某个点之后(主要活动开始并且显示片段的时候),FinalizerDaemon会停止处理对象并且垃圾堆积不断.看一下线程转储,它似乎停留在ReferenceQueue.remove()
:
"FinalizerDaemon@4461" daemon prio=5 waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:423)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
- locked <0x1173> (a java.lang.ref.ReferenceQueue)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
at java.lang.Thread.run(Thread.java:818)
Run Code Online (Sandbox Code Playgroud)
但队列并非空.如果我在使用app一段时间之后转储堆,那么队列实际上是数千个条目.数据结构也看起来不破:
在分配和垃圾收集后再次转储更多显示队列的头部与以前相同的Matrix实例.
现在,我注意到了这一点,因为我保留了一些C++对象,需要在某些时候释放它们.虽然我怀疑终结器调用JNI函数并在C++端做一些愚蠢的操作可能会以某种方式破坏它,但我的所有日志都表明所有终结器都运行良好并返回而不会抛出任何东西,直到它们随机停止被调用.此外,最终的调用不应该打破守护进程,除了整个应用程序或其他东西,因为看门狗应该处理运行时间太长并抛出异常的终结器.
我尝试了一个显式的System.runFinalization()
,它所做的只是永远挂起主线程,等待从未运行的守护进程.
知道怎么会这样吗?
我有个问题.我过去4-5周一直在Eclipse中使用Android,从未遇到过VM的问题(它们很慢,是的.但从未崩溃).
现在,我相信自从4.2开始为uni开始新项目(下周截止日期)时,由于"Kernel Panic"(最后的resport),我的4.2 VM突然开始崩溃.
我想问一下我能做什么,也许下载一个修补程序或任何东西.API和Eclipse都是最新的,或者我的计算机可能有问题?(不知何故,甚至我的旧VM(2.3.3,3.1和4.1)在99%的时间内都会在启动时崩溃)
任何建议都将受到高度赞赏.这里是Crash-Log的开头:
进程:emulator64-arm [1334]路径:
/Users/USER/*/emulator64-arm标识符:emulator64-arm版本:??? 代码类型:X86-64(Native)父进程:eclipse [1156]用户ID:501日期/时间:2012-12-01 00:25:27.469 +0100操作系统版本:Mac OS X 10.8.2(12C2034)报告版本:10
自上次报告以来的间隔时间:130686秒自上次报告以来崩溃:自上次报告以来每次应用程序崩溃:32匿名UUID:ABE51F99-F7A9-2595-016E-C47FFD1F6C50
崩溃的线程:0调度队列:com.apple.main-thread
异常类型:EXC_BAD_ACCESS(SIGSEGV)异常代码:KERN_INVALID_ADDRESS位于0x0000000000000000
VM区域接近0: - > __TEXT 0000000100000000-0000000100247000 [2332K] rx/rwx SM = COW/Users/USER/*
线程0 Crashed :: Dispatch queue:com.apple.main-thread
是否有Surface,SurfaceHolder,EGLSurface,SurfaceView,GLSurfaceView,SurfaceTexture和TextureView的详细说明?特别是:
android surfaceview glsurfaceview surfaceflinger textureview
我知道在Android平台上有Dalvik(JVM)堆和Native堆.Dalvik GC在本机堆上没有工作.但我不确定这是如何工作的,我的意思是Android操作系统是如何将它们分开的?
可能的情况1:由独立的内存硬件组成(我不相信太多)
可能的情况2:Android操作系统对两个堆都有固定的内存量
可能的情况3:Android OS必须在必要时将部分Dalvik内存堆分配为本机堆,因此本机堆和Dalvik堆的大小是灵活的.
哪一个是真的,或者我没有提到的可能性?
理想情况下,我想完成两个目标:
Camera
预览将预览数据传递给MediaCodec
编码器Surface
.我可以创建Surface
使用MediaCodec.createInputSurface()
但是Camera.setPreviewDisplay()
需要a SurfaceHolder
,而不是a Surface
. Camera
预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容).如果编码器没有参与,那么我会使用a SurfaceView
,但这似乎不适用于这种情况,因为SurfaceView
创建了自己的编码器Surface
,我认为我需要使用创建的编码器MediaCodec
.我在网上搜索了很多解决方案,但没有找到解决方案.bigflake.com上的一些例子似乎是朝着正确方向迈出的一步,但他们采取了一种方法,增加了一堆我想避免的EGL/SurfaceTexture开销.我希望有一个简单的例子或解决方案,我能得到Camera
并且MediaCodec
不涉及EGL或纹理更直接交谈.
我是Android开发的新手,我发现很难在camera2 api上找到好的例子.
我在大多数问题上慢慢地工作,但在这个问题上,我被困住了.在默认相机中,当您触摸屏幕进行对焦时,它会暂时显示焦点区域的矩形.我想做类似的事情(或者在这种情况下,完全相同的事情开始,所以我可以弄明白).
我在某处看到(我认为SDK文档中的TextureView页面),当它被用作相机预览时,你无法在textureview上绘制 - 并且调用lock方法将返回null而不是画布.
我在网上找到了这个:https://github.com/commonsguy/vidtry/ 但我无法让它工作.我或者得到错误说我的主视图不能投射到我的可绘制视图,反之亦然 - 或者我的可绘制视图位于顶部并使屏幕变黑 - 或者它在底部并且不会响应触摸事件(并试图强制从上面的视图中执行点击它会导致崩溃.)
我卡住了!任何人都可以给我一个解释或示例,说明如何在事件位置上绘制矩形几秒钟?
谢谢!
android android-layout android-camera android-canvas textureview
android ×10
mediacodec ×3
textureview ×3
android-ndk ×2
surfaceview ×2
aac ×1
audiorecord ×1
camera ×1
dalvik ×1
eclipse ×1
encoder ×1
h.264 ×1
java ×1
kernel ×1
macos ×1
memory ×1
opengl-es ×1
openmax ×1
stagefright ×1
yuv ×1