为了便于理解,先说一下 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()