免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
FFMpeg壓縮Android攝像頭數(shù)據(jù)寫(xiě)成H264格式文件


Android端獲取攝像頭數(shù)據(jù)有好幾種。我使用的是onPreviewFrame(byte data[],Camera camera);這個(gè)回調(diào)函數(shù)

遇到的問(wèn)題:

問(wèn)題1、打印了下data[]的長(zhǎng)度,是3110400。

手機(jī)攝像頭像素是1920*1080=2073600

3110400/2073600=1.5,這個(gè)1.5就懂了。

data[]里默認(rèn)存放的是YUV420SP格式的幀,有YUV三個(gè)分量。其中像素占2/3,就是Y分量,是控制整體的視頻內(nèi)容的。而U、V占剩下的1/3,是控制顏色的。所以1920*1080=2073600算出來(lái)的是Y分量。剩下的是U和V的分量。幀的width和height就是Y分量的width和height。

問(wèn)題2、YUV格式有好幾種,有YUV420SP有YUV420P,等等,只看這兩種吧。


這兩張圖里也能看出來(lái),Y分量通常占整個(gè)幀長(zhǎng)度的2/3。

第一張YUV420SP,下邊U和V是相互交錯(cuò)著的,而YUV420P的U和V就很整齊。YUV420P這個(gè)性質(zhì)很重要,我們要利用這個(gè)性質(zhì),使分離YUV分量變得容易。


問(wèn)題3、改變onPreviewFrame()回調(diào)的data[]的大小,改變預(yù)覽幀data[]的格式。

直接上

[java] view plain copy
print?
  1. <span style="white-space:pre">    </span>Camera.Parameters parameters = mCamera.getParameters();  
通過(guò)parameters來(lái)設(shè)置預(yù)覽幀的大?。ň褪歉淖儙南袼兀?,和預(yù)覽幀的格式。

[java] view plain copy
print?
  1. parameters.setPreviewSize(864480);  
  2. parameters.setPreviewFormat(ImageFormat.YV12);  

如果你不設(shè)置setPreviewFormat的話(huà),默認(rèn)回調(diào)的data[]格式是YUV420SP。CbCr就是U和V。Cb控制藍(lán)色,Cr控制紅色。直接點(diǎn)進(jìn)源碼里看就好。

所以一定要設(shè)置一下格式為ImageFormat.YV12,就是YUV420P。ImageFormat.YV12這個(gè)是我在prameters.setPreviewFormat(),下圖里找到的。。。

最后,最重要一點(diǎn):把parameters設(shè)置回去!我忘了設(shè)置,調(diào)了好久,發(fā)現(xiàn)data[]永遠(yuǎn)是3110400大小,改了prameters.setPreviewFormat()也沒(méi)用。

[java] view plain copy
print?
  1. mCamera.setParameters(parameters);  

Android端完了,剩下的就是底層NDK端FFMpeg的調(diào)試。

講講遇到的問(wèn)題:

問(wèn)題1、由于開(kāi)始先VS上做的實(shí)驗(yàn),然后移植。結(jié)果導(dǎo)致把所有代碼都放到一個(gè)jni函數(shù)里,結(jié)果一直崩潰,原來(lái)是:因?yàn)槊恳粠家獋鬟M(jìn)來(lái)壓縮,所以一直在執(zhí)行av_register_all();等等類(lèi)似代碼。導(dǎo)致崩潰。所以要把這類(lèi)初始化的過(guò)程,單獨(dú)放到一個(gè)native方法里。把AVCodecContext *pCodecCtx;這種聲明成全局變量。

問(wèn)題2、把傳進(jìn)來(lái)的jbyteArray轉(zhuǎn)換成jbyte *,忘了在結(jié)束的時(shí)候釋放掉,導(dǎo)致運(yùn)行一秒鐘左右就會(huì)內(nèi)存溢出。

[cpp] view plain copy
print?
  1. <span style="font-size:18px;">jbyte *yuv420sp = (jbyte*) (*env)->GetByteArrayElements(env, yuvdata, 0);</span>  
最后一定要有這句,來(lái)把內(nèi)存釋放掉
[cpp] view plain copy
print?
  1. <span style="font-size:18px;">(*env)->ReleaseByteArrayElements(env, yuvdata, yuv420sp, 0);</span>  

問(wèn)題3、在jni里寫(xiě)本地文件,路徑為char filename_out[] = "/storage/emulated/0/yourname.h264";

JAVA

[java] view plain copy
print?
  1. public class MainActivity extends Activity implements Camera.PreviewCallback,  
  2.         SurfaceHolder.Callback {  
  3.     List<Size> list;  
  4.     SurfaceView mSurfaceView;  
  5.     SurfaceHolder mSurfaceHolder;  
  6.     Camera mCamera;  
  7.     TextView tv;  
  8.     Handler mHandler = new Handler() {  
  9.         public void handleMessage(android.os.Message msg) {  
  10.             switch (msg.what) {  
  11.             case 1:  
  12.                 byte[] bytedata = msg.getData().getByteArray("messageyuvdata");  
  13.                 if (bytedata != null) {  
  14.                     // tv.setText(temp+"");  
  15.                     int count = addVideoData(bytedata);  
  16.                     tv.setText("length:"+length);  
  17.                 }  
  18.                 break;  
  19.             case 2 :  
  20.                 String s = msg.getData().getString("supportFrameSize");  
  21.                 tv.setText(s);  
  22.                 break;  
  23.             }  
  24.         };  
  25.     };  
  26.   
  27.     int temp = 0;  
  28.     int length = 0;  
  29.     @Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         // TODO Auto-generated method stub  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.         tv = (TextView) findViewById(R.id.tv);  
  35.         temp = FFMpegLib.getVersion();  
  36.         mSurfaceView = (SurfaceView) this.findViewById(R.id.surfaceview);  
  37.         mSurfaceHolder = mSurfaceView.getHolder();  
  38.         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  39.         mSurfaceHolder.addCallback(this);  
  40.   
  41.     }  
  42.   
  43.     @Override  
  44.     public void onPreviewFrame(byte[] data, Camera camera) {  
  45.         length = data.length;  
  46.         Log.i("log", data + "");  
  47.         Message msg = new Message();  
  48.         Bundle bl = new Bundle();  
  49.         bl.putByteArray("messageyuvdata", data);  
  50.         msg.setData(bl);  
  51.         msg.what = 1;  
  52.         mHandler.sendMessage(msg);  
  53.     }  
  54.   
  55.     @Override  
  56.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  57.             int height) {  
  58.         // TODO Auto-generated method stub  
  59.         mCamera.startPreview();  
  60.     }  
  61.   
  62.     @Override  
  63.     public void surfaceCreated(SurfaceHolder holder) {  
  64.         // TODO Auto-generated method stub  
  65.         // 打開(kāi)前置攝像頭  
  66.         mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);  
  67.   
  68.         try {  
  69.             Camera.Parameters parameters = mCamera.getParameters();  
  70.             List<Integer> supportedPictureFormats = parameters  
  71.                     .getSupportedPictureFormats();  
  72.             for (Integer integer : supportedPictureFormats) {  
  73.                 Log.i("sun", integer + "");  
  74.             }  
  75.             list = parameters.getSupportedPreviewSizes();  
  76.             parameters.setPreviewSize(864480);  
  77.             parameters.setPreviewFormat(ImageFormat.YV12);  
  78.             parameters.setPreviewFpsRange(2020); // 每秒顯示20~30幀  
  79.             parameters.setPictureFormat(PixelFormat.JPEG); // 設(shè)置圖片格式  
  80.             //parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);  
  81.             //parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);  
  82.               
  83.             String supportFrameSize = null;  
  84.             for (int i = 0; i < list.size(); i++) {  
  85.                 int width =list.get(i).width;  
  86.                 int height =list.get(i).height;  
  87.                 supportFrameSize = supportFrameSize+width+"-"+height+"||||||";  
  88.             }  
  89.               
  90.               
  91.             Message msg = new Message();  
  92.             Bundle bl = new Bundle();  
  93.             bl.putString("supportFrameSize", supportFrameSize);  
  94.             msg.setData(bl);  
  95.             msg.what = 2;  
  96.             mHandler.sendMessage(msg);  
  97.             mCamera.setParameters(parameters);  
  98.               
  99.         } catch (Exception e) {  
  100.             e.printStackTrace();  
  101.         }  
  102.           
  103.         // 開(kāi)始預(yù)覽  
  104.         try {  
  105.             // 設(shè)置哪個(gè)surfaceView顯示圖片  
  106.             mCamera.setPreviewDisplay(mSurfaceHolder);  
  107.         } catch (IOException e) {  
  108.             e.printStackTrace();  
  109.         }  
  110.           
  111.         // 設(shè)置預(yù)覽幀的接口,就是通過(guò)這個(gè)接口,我們來(lái)獲得預(yù)覽幀的數(shù)據(jù)的  
  112.           
  113.         mCamera.setPreviewCallback(MainActivity.this);  
  114.         mCamera.startPreview();  
  115.     }  
  116.   
  117.     @Override  
  118.     public void surfaceDestroyed(SurfaceHolder holder) {  
  119.         // TODO Auto-generated method stub  
  120.         mCamera.stopPreview();  
  121.         mCamera.release();  
  122.     }  
  123.   
  124.     public synchronized int addVideoData(byte[] data) {  
  125.         int s = FFMpegLib.Encoding(data);  
  126.         return s;  
  127.     }  
  128.   
  129.     @Override  
  130.     protected void onStart() {  
  131.         super.onStart();  
  132.     }  
  133.     @Override  
  134.     protected void onDestroy() {  
  135.         super.onDestroy();  
  136.         FFMpegLib.CloseVideo();  
  137.     }  
  138. }  



JNI

[cpp] view plain copy
print?
  1. #include <string.h>  
  2. #include <stdio.h>  
  3. #include <android/log.h>  
  4. #include <stdlib.h>  
  5. #include <jni.h>  
  6. #include <ffmpeg/libavcodec/avcodec.h>  
  7. #include "ffmpeg/libavformat/avformat.h"  
  8. #include "ffmpeg/libavdevice/avdevice.h"  
  9. #include "ffmpeg/libavutil/avutil.h"  
  10. #include "ffmpeg/libavutil/opt.h"  
  11. #include "ffmpeg/libavutil/imgutils.h"  
  12. #include "ffmpeg/libavutil/log.h"  
  13.   
  14. #define TEST_H264  1  
  15.   
  16. #ifdef ANDROID  
  17. #include <jni.h>  
  18. #include <android/log.h>  
  19. #define LOGE(format, ...)  __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)  
  20. #define LOGI(format, ...)  __android_log_print(ANDROID_LOG_INFO,  "(^_^)", format, ##__VA_ARGS__)  
  21. #else  
  22. #define LOGE(format, ...)  printf("(>_<) " format "\n", ##__VA_ARGS__)  
  23. #define LOGI(format, ...)  printf("(^_^) " format "\n", ##__VA_ARGS__)  
  24. #endif  
  25.   
  26. AVCodec *pCodec;  
  27. AVCodecContext *pCodecCtx = NULL;  
  28. int i, ret, got_output;  
  29. FILE *fp_out;  
  30. AVFrame *pFrame;  
  31. AVPacket pkt;  
  32. int y_size;  
  33. int framecnt = 0;  
  34. char filename_out[] = "/storage/emulated/0/yourname.h264";  
  35. int in_w = 864, in_h = 480;  
  36. int count = 0;  
  37.   
  38. JNIEXPORT jint JNICALL Java_com_cpi_ffmpeg_FFMpegLib_getVersion(JNIEnv *env,  
  39.         jclass jclass) {  
  40.     avcodec_register_all();  
  41.   
  42.     pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);  
  43.     if (!pCodec) {  
  44.         printf("Codec not found\n");  
  45.         return -1;  
  46.     }  
  47.     pCodecCtx = avcodec_alloc_context3(pCodec);  
  48.     if (!pCodecCtx) {  
  49.         printf("Could not allocate video codec context\n");  
  50.         return -1;  
  51.     }  
  52.     pCodecCtx->bit_rate = 400000;  
  53.     pCodecCtx->width = in_w;  
  54.     pCodecCtx->height = in_h;  
  55.     pCodecCtx->time_base.num = 1;  
  56.     pCodecCtx->time_base.den = 20;  
  57.     pCodecCtx->gop_size = 10;  
  58.     pCodecCtx->max_b_frames = 5;  
  59.     pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;  
  60.   
  61.     av_opt_set(pCodecCtx->priv_data, "preset""superfast", 0);  
  62. //  av_opt_set(pCodecCtx->priv_data, "preset", "slow", 0);  
  63.     av_opt_set(pCodecCtx->priv_data, "tune""zerolatency", 0);  
  64.   
  65.   
  66.   
  67.     if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {  
  68.         printf("Could not open codec\n");  
  69.         return -1;  
  70.     }  
  71.     if ((fp_out = fopen(filename_out, "wb")) == NULL) {  
  72.         return -1;  
  73.     }  
  74.     y_size = pCodecCtx->width * pCodecCtx->height;  
  75.   
  76.     return 1;  
  77. }  
  78. JNIEXPORT jint JNICALL Java_com_cpi_ffmpeg_FFMpegLib_Encoding(JNIEnv *env,  
  79.         jclass jclass, jbyteArray yuvdata) {  
  80.   
  81.     jbyte *yuv420sp = (jbyte*) (*env)->GetByteArrayElements(env, yuvdata, 0);  
  82.   
  83. //  av_opt_set(pCodecCtx->priv_data, "preset", "superfast", 0);  
  84. //  av_opt_set(pCodecCtx->priv_data, "tune", "zerolatency", 0);  
  85.   
  86.   
  87.     pFrame = av_frame_alloc();  
  88.     if (!pFrame) {  
  89.         printf("Could not allocate video frame\n");  
  90.         return -1;  
  91.     }  
  92.     pFrame->format = pCodecCtx->pix_fmt;  
  93.     pFrame->width = pCodecCtx->width;  
  94.     pFrame->height = pCodecCtx->height;  
  95.   
  96.     ret = av_image_alloc(pFrame->data, pFrame->linesize, pCodecCtx->width,  
  97.             pCodecCtx->height, pCodecCtx->pix_fmt, 16);  
  98.     if (ret < 0) {  
  99.         printf("Could not allocate raw picture buffer\n");  
  100.         return -1;  
  101.     }  
  102.   
  103.     av_init_packet(&pkt);  
  104.     pkt.data = NULL; // packet data will be allocated by the encoder  
  105.     pkt.size = 0;  
  106.   
  107.     //Read raw YUV data  這里出錯(cuò)了,是按YUV_SP處理的 應(yīng)該是YUV_P  
  108.     pFrame->data[0] = yuv420sp; //PCM Data  
  109.     pFrame->data[1] = yuv420sp + y_size * 5 / 4; // V  
  110.     pFrame->data[2] = yuv420sp + y_size; // U  
  111.     pFrame->pts = count;  
  112.     count++;  
  113.     /* encode the image */  
  114.     ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);  
  115.     int sizee = pkt.size;  
  116.     if (ret < 0) {  
  117.         printf("Error encoding frame\n");  
  118.         return -1;  
  119.     }  
  120.     if (got_output) {  
  121.         printf("Succeed to encode frame: %5d\tsize:%5d\n", framecnt, pkt.size);  
  122.         framecnt++;  
  123.         fwrite(pkt.data, 1, pkt.size, fp_out);  
  124.         av_free_packet(&pkt);  
  125.         av_freep(&pFrame->data[0]);  
  126.         av_frame_free(&pFrame);  
  127.         //(*env)->ReleaseByteArrayElements(env, yuvdata, ydata, 0);  
  128.         // return framecnt;  
  129.     }  
  130.     //av_freep(&pFrame->data[0]);  
  131.     //av_frame_free(&pFrame);  
  132.     (*env)->ReleaseByteArrayElements(env, yuvdata, yuv420sp, 0);  
  133.     return 1;  
  134. }  
  135.   
  136. JNIEXPORT jint JNICALL Java_com_cpi_ffmpeg_FFMpegLib_CloseVideo(JNIEnv *env,  
  137.         jclass jclass) {  
  138.   
  139.     for (got_output = 1; got_output; i++) {  
  140.         ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);  
  141.         if (ret < 0) {  
  142.             printf("Error encoding frame\n");  
  143.             return -1;  
  144.         }  
  145.         if (got_output) {  
  146.             printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",  
  147.                     pkt.size);  
  148.             fwrite(pkt.data, 1, pkt.size, fp_out);  
  149.             av_free_packet(&pkt);  
  150.         }  
  151.     }  
  152.   
  153.     fclose(fp_out);  
  154.     avcodec_close(pCodecCtx);  
  155.     av_free(pCodecCtx);  
  156.     av_freep(&pFrame->data[0]);  
  157.     av_frame_free(&pFrame);  
  158.     return 0;  
  159. }  
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Android PC投屏簡(jiǎn)單嘗試(錄屏直播)3
ffmpeg解碼流程 turorial5詳解
100行代碼實(shí)現(xiàn)最簡(jiǎn)單的基于FFMPEG+SDL的視頻播放器(SDL1.x)
AndroidStudio 中使用FFMPEG
學(xué)習(xí)FFmpeg API – 解碼視頻
libavformat/libavcodec學(xué)習(xí)(轉(zhuǎn)) - 視頻開(kāi)發(fā) - 在路上........
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服