android顯示相關實現調試手記

來源:互聯網
上載者:User

 首先來看一下總得初始化介面實現,裡面是先開啟裝置,在開啟裝置裡面會設定輸入視頻源,查詢視頻裝置驅動能力,緊接著設定視頻模式,是V4L2_MODE_VIDEO的,再來設定video的參數,比如寬高、pixel的格式、filed等,然後再申請buffer,綁定匹配buffer地址,最後就是啟動視頻裝置資料流,整個裝置就工作起了。代碼具體如下:   [cpp] status_t CCSIDecoderHardware::v4l2Init(int mOldSystem)  {      F_LOG;        CHECK_ERROR(openCameraDev());                // set capture mode      struct v4l2_streamparm params;          params.parm.capture.timeperframe.numerator = 1;      params.parm.capture.timeperframe.denominator = 25;      params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;      params.parm.capture.capturemode = V4L2_MODE_VIDEO;//V4L2_MODE_IMAGE        v4l2setCaptureParams(¶ms);        // set v4l2 device parameters      CHECK_ERROR(v4l2SetVideoParams(mOldSystem));            // v4l2 request buffers      CHECK_ERROR(v4l2ReqBufs());            // v4l2 query buffers      CHECK_ERROR(v4l2QueryBuf());            // stream on the v4l2 device      CHECK_ERROR(v4l2StartStreaming());        return OK;  }         筆者移植了tryFmt()這個用來尋找對應的fmt,會有一下參數關聯,比如輸入CSI的fmt格式,CSI輸出資料格式、CSI資料介面類型等,程式碼範例如下:    [cpp] struct v4l2_fmtdesc fmtdesc;  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  for(int i = 0; i < 12; i++)  {      fmtdesc.index = i;      if (-1 == ioctl (mV4l2Handle, VIDIOC_ENUM_FMT, &fmtdesc))      {          break;      }      LOGV("format index = %d, name = %s, v4l2 pixel format = %x\n",          i, fmtdesc.description, fmtdesc.pixelformat);        if (fmtdesc.pixelformat == format)      {          return OK;      }  [cpp]  }  要設定video的參數; [cpp] struct v4l2_format format;    LOGD("#####################VIDIOC_S_PARM\n");  memset(&format, 0, sizeof(format));         format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;          format.fmt.pix.width  = mVideoWidth;          format.fmt.pix.height = mVideoHeight;          format.fmt.pix.pixelformat = mVideoFormat; //pix_fmt  format.fmt.pix.field = V4L2_FIELD_NONE;    ret = ioctl(mV4l2Handle, VIDIOC_S_FMT, &format);   if (ret < 0)   {       LOGE("VIDIOC_S_FMT Failed: %s", strerror(errno));       return ret;   }         得起一個線程來負責讀資料幀,以及把資料幀資料處理掉。在這個線程中還需要加入即時檢測視頻訊號的有無,以及訊號的制式,是NTSC還是PAL,監測代碼如下: [cpp]  struct v4l2_control ctrl;   ctrl.value = 0;   ctrl.id = V4L2_CID_BRIGHTNESS;/*just use this channel to read fmt & detect signals*/  ret = ioctl (mV4l2Handle, VIDIOC_G_CTRL, &ctrl);   if (ret < 0)    {       LOGE("vidioc_g_ctrl: %s", strerror(errno));   }     LOGE("get_system ctrl.value 0x%02x", ctrl.value);    mDetectcvbsSignal = ((ctrl.value & 0x10) == 0x10)? 0:1 ;/*bit4 1:no signal 0: has signal*/         fmt = ctrl.value & 0x7;   if((0 == fmt) || (1 == fmt))       *__system = 0;/*NTSC*/  else     *__system = 1;/*PAL*/         筆者在訊號制式的處理上稍微做了一下變通,因為這兩種制式在大小上是不一樣,但是我們可以用大一點的那個buffer,這樣我們就不需要重新去設定這些buffer,而只需要控制後面取buffer的資料大小就可以,這樣也是簡便了一下。同時,筆者在調試發現NTSC的制式上,開始會有是十幾個像素高度的髒資料,顯示是亂的,這樣我用大buffer就可以把N制的整個資料都截下來,起始地址移動一下就可以了,這樣確實真實有效,裡面使用了native window的操作,直接把資料幀的buffer地址賦給了hwcoposer,也就是到核心裡的硬體驅動裡,這樣就減少了資料拷貝的工作,cpu使用率非常低,這樣主晶片可以幹很多其他的事情。代碼如下: [cpp]  int hight = 0;  hight = (mOldSystem == 0)? 480:576;  LOGV("mOldSystem = %d, hight =%d\n", mOldSystem, hight);  [cpp]         ret = native_window_set_buffers_geometryex(mPreviewWindow ,             mVideoWidth,     hight,HWC_FORMAT_YUV422PLANAR_UV_COMBINED, //*/HWC_FORMAT_DEFAULT,HWC_FORMAT_YUV420PLANAR                 0);                                    if (ret != NO_ERROR)           {              LOGE("%s: Error in set_buffers_geometry %d -> %s",__FUNCTION__, -ret, strerror(-ret));              return ret;          }  ....      <p> /*when NTSC shoud shift display buffer*/   overlay_para.bProgressiveSrc = 0;   overlay_para.bTopFieldFirst = 1;   overlay_para.pVideoInfo.frame_rate = 25000;   if(1 == mOldSystem) {/*PAL*/    overlay_para.top_y   = (unsigned int)buf.m.offset;     overlay_para.top_c   = (unsigned int)buf.m.offset +  mVideoWidth * mVideoHeight;   } else {/*NTSC*/     overlay_para.top_y   = (unsigned int)buf.m.offset+ 1440;/* 720*20 20 point*/     overlay_para.top_c   = (unsigned int)buf.m.offset +  mVideoWidth * mVideoHeight+7200;/* 720*20*1/2 20 point*/     }   overlay_para.bottom_y  = 0;   overlay_para.bottom_c  = 0;   overlay_para.number  = 0;</p><p> if (mOverlayFirstFrame)   {    LOGD("first frame true");    overlay_para.first_frame_flg = 1;    mOverlayFirstFrame = false;   }   else   {    overlay_para.first_frame_flg = 0;   }</p><p> ret = mPreviewWindow->perform(mPreviewWindow, NATIVE_WINDOW_SETPARAMETER, HWC_LAYER_SETFRAMEPARA, (uint32_t)&overlay_para);   if (ret != OK)   {    LOGE("NATIVE_WINDOW_SETPARAMETER failed");    return ret;</p>          HWC_FORMAT_YUV422PLANAR_UV_COMBINED是筆者自訂的格式,全志平台裡沒有做這種格式,在hwc的硬體抽象層裡需要添加需相應的代碼實現,貼一部分如下: [cpp]  case HWC_FORMAT_YUV422PLANAR_UV_COMBINED:      disp_format = DISP_FORMAT_YUV422;      fb_mode = DISP_MOD_NON_MB_UV_COMBINED;      disp_seq = DISP_SEQ_UYVY;      break;        當然,以後如果要做錄影的話,就需要把資料幀截下來,通過多媒體那邊的庫來壓縮編碼存檔案,這個工作可以參考camera裡面的實現。硬體抽象層的代碼就差不多了。JNI以及應用APK,都可以再TVD上稍微改改,難度不大,這裡就不再詳述。貼一張整個實現後的應用吧!   

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.