2011年12月18日
Galaxy Nexusって無音カメラ標準(音でないし??)
なぜか??カメラでシャッター押しても音が標準で出ません。
カメラアプリのソース弄っても、音出ないし???
なぜ????
HTC Desireもボリューム下げると音でません???
DoCoMoらしからぬ手落ち仕様ですか~(笑
で・・・・本題
スマホで音出ないカメラを作ろうとするとハマるのが、データ形式
そのままデータをbitmapに入れると、緑の線だらけの不思議な画像の出来上がり。
プレビュー画像をキャプチャーするので(かすめとる?)音が出ないっていえば当然
ま~画質が落ちるのはいかしかたないのですが・・・・・・・
ソースはこんな感じ
mCamera.setPreviewCallback(new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
int width = 0;// プレビューの幅
int height =0; // プレビューの高さ
width =preview_size_w;//取得したプレビューの幅
height =preview_size_h;//size.height; // 取得したプレビューの高さ
if(bmp!=null)
{
bmp.recycle();
bmp=null;
}
if(data != null)//正しい値を返さない機種でエラーの対策
{
width =preview_size_w;// 取得したプレビューの幅
height =preview_size_h;
if(mTempData == null)
{
}
if(spybmp!=null)
{
spybmp.recycle();
spybmp=null;
}
if(bmp!=null)
{
bmp.recycle();
bmp=null;
}
spybmp =
Bitmap.createBitmap(decodeYUV(data, width, height),width,
height,Bitmap.Config.ARGB_8888);
float rate=0;
rate=0.5f;//ここは縮小レートですので適当~
Matrix matrix = new Matrix();
matrix.postScale(rate, rate);
float pw=(float)width;
float ph=(float)height;
bmp =Bitmap.createBitmap(spybmp, 0, 0, (int)pw, (int)ph, matrix, true);
みたいな感じに作ります!
で、ミソは
decodeYUV(data, width, height)って感じの自作c++関数を呼び出します
それと
width =preview_size_w;// 取得したプレビューの幅
height =preview_size_h;
画面の幅と高さの取得にも癖があって、ここもハマります(笑
プレビューサイズと撮影サイズのアスペクトが一致してないと落ちますし、レイアウトのアスペクトが一致してないとこれまた強制終了します。
機種依存が強いので(全世界600種類の携帯の依存性をクリアしなければなりませんが・・)通常の方法で取得した値は嘘八百なんてこともあったりして、緑の画面になったりもしますので、ここはノウハウでしょうね~上記の二つがクリアできれば、あとは簡単!!
それと・・・・
if(bmp!=null)
{
bmp.recycle();
bmp=null;
}
も大事。Androidはすぐにメモリーエラーで落ちるので自前で明示的にでっかい画像Bitmapを解放しなければなりません。
自作関数使うのはjavaでyuvデータをbitmapにでコードしてたら時間かかりすぎるのとOut of memory
通称OOMで簡単に落ちまくるための対策です(笑
だってBITMAPの配列つくるのにですよ!860X480X4(R/G/B/Alphaが4要素)の配列確保したとたんに落ちます!確実に!
あ~Javaって嫌い!!って感じになっちゃいます。
てなわけで、こんな嫌~な部分はc++で作っちゃいます。
以下のc++サンプルはネットにまったくありません。javaは沢山ありますが・・・(それも英語が多い)
本家で公開していたサンプルをc++にしてみました。
★jniで書き出す場合のデーコード部分のソースを出血大サービス~です。
JNIEXPORT int JNICALL Java_sample_yuv(JNIEnv *env, jobject obj,
jbyteArray yuvSrc,jintArray yuvDest, jint width, jint height,jint size)
{
jbyte *yuv420sp = (*env)->GetByteArrayElements( env, yuvSrc, 0 );
jint *out = (*env)->GetIntArrayElements( env, yuvDest, 0 );
int Y, Cr = 0, Cb = 0;
int i,i2;
int index=0;
int jDiv2=0;
int c0ff=0;
for(i = 0; i < height; i++)
{
index = i * width;
jDiv2 = i >> 1;
for(i2 = 0; i2 < width; i2++)
{
Y = yuv420sp[index];
if(Y < 0)
{
Y += 255;
}
if((i2 & 0x1) != 1)
{
c0ff = size + jDiv2 * width + (i2 >> 1) * 2;
Cb = yuv420sp[c0ff];
if(Cb < 0)
{
Cb += 127;
}
else
{
Cb -= 128;
}
Cr = yuv420sp[c0ff + 1];
if(Cr < 0)
{
Cr += 127;
}
else
{
Cr -= 128;
}
}
// red
int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
if(R < 0)
{
R = 0;
}
else if (R > 255)
{
R = 255;
}
// green
int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
if(G < 0)
{
G = 0;
}
else if (G > 255)
{
G = 255;
}
// blue
int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
if(B < 0)
{
B = 0;
}
else if (B > 255)
{
B = 255;
}
out[index] = 0xff000000 + (B << 16) + (G << 8 ) + R;
index++;
}
}
(*env)->ReleaseByteArrayElements( env, yuvSrc, yuv420sp, 0 );
(*env)->ReleaseIntArrayElements( env, yuvDest, out, 0 );
}
てな関数をc++で作っておけば、あ~ら不思議、落ちません
でもね、Nexusは音しないので、いらないかも(笑
※悪用厳禁です。
ブログ一覧 | 日記
Posted at
2011/12/18 22:07:46
今、あなたにおすすめ