为了便于理解,先说一下 Camera 的帧数据的格式,目前我碰到的都是 yuv420sp 格式,所以这个 Demo 只处理了这一种格式的数据。 代码中 YuvRender 就是用来处理这种格式的,它是一个 Render 对象。
type Render interface {
// Init render, userdata is ignore
Init()
Draw(pixels interface{})
Release()
// SetProperty
// wW, wH is windows/client width, height
// iW, iH is image width, height
// x, y, w, h is draw image to rect
// op is ROTATION?? | FLIPHOR | FLIPVER
SetProperty(wW, wH int, iW, iH int, x, y, w, h int, op int)
// 验证 pixels 是否符合指定 width、height
Validate(width, height int, pixels interface{}) bool
}
主要是用来绘制和检查数据是否有效。
如果出现其它格式的数据,同样实现一个 Render 。
并在这里加上对它的支持:
switch cam.imgFormat {
case "yuv420sp":
cam.irender = &render.YuvRender{}
case "????": // 新加的格式
cam.irender = ????
default:
log.Println("not support format:", cam.imgFormat)
return
}
如果 Demo 不能正常跑,一方面看 cameraInit 是否成功, 另外就是看一下数据格式。
func cameraInit(id int, usercb func(w, h int, img []byte) bool) *cameraObj {
cam := &cameraObj{}
cb := func(buffer []byte) bool {
// init done
if atomic.CompareAndSwapInt32(&cam.camStat, NONE, READY) {
return true
}
wh := cam.previewSizes[cam.previewIndex]
if cam.camStat == RESIZING && cam.irender.Validate(wh[0], wh[1], buffer) {
cam.ResetProperty()
atomic.CompareAndSwapInt32(&cam.camStat, RESIZING, READY)
}
...
runtime.Gosched()
return true
}
cam.Camera = camera.Connect(id, cb)
if cam.Camera == 0 {
log.Println("Cammera connect fail")
return nil
}
...
// 第一个为默认分辨率
// 因 camera 还未初始化完,需就异步执行
go func() {
runtime.LockOSThread()
for cam.camStat == NONE {
time.Sleep(time.Millisecond * 100)
}
cam.setPreviewSize(0)
}()
return cam
}
cam.Camera = camera.Connect(id, cb)cam.irender.Validate(...)runtime.Gosched()
...
cam.SetFlashMode(camera.FLASH_MODE_TORCH)
...
cam.SetFlashMode(camera.FLASH_MODE_OFF)
...
cam.ApplyProperties()
FLASH_MODE_TORCHcam.ApplyProperties()cam.ApplyProperties()