void mjpeg_decoder_t::releaseBuffer(unsigned displayIdx)
{
	unsigned mask = 1<<displayIdx ;
	assert(displayIdx < fbcount);
	assert(0 == (decoder_fbs & mask));
	assert(0 != (app_fbs & mask));
	app_fbs &= ~mask ;
	decoder_fbs |= mask ;

        RetCode err = vpu_DecClrDispFlag(handle_, displayIdx);
	if( RETCODE_SUCCESS == err ){
		debugPrint("%s: released buffer %u\n", __func__, displayIdx );
	}
	else
		fprintf(stderr, "%s: Error %d releasing buffer %u\n", __func__, err, displayIdx );
	startDecode();
}
//-----------------------------------------------
void captureApp::endCapture(bool cancelSave){
	printf("endCapture\n");
	if( state == CAP_STATE_CAPTURE ){
		ofShowCursor();
		light.lightOn();		
		
		if( bEnableOsc ){
			printf("----------sending osc message (capture stopped)\n");
			ofxOscMessage m;
			m.addStringArg("CaptureStopped");
			m.addStringArg(""); //folder transferred eg: decode-NYC-12939327117
			m.addStringArg("");	//just the timestamp as a string eg: 12939327117
			m.addIntArg(0);		//num images to be transfered
			oscTx.sendMessage(m);
		}	
		
		if( panel.getValueB("B_FACE_TRIGGER") ){
			bNeedsToLeaveFrame = true;
		}else{
			bNeedsToLeaveFrame = false;
		}
		
		scanningSound.stop();
		
		if( !cancelSave ){
			if( panel.getValueI("postCapture") > POST_CAPTURE_SAVE ){
				startDecode();
			}else{
				prepareExportFramesToDisk();
				startThread(true, false);
			}
		}else{
			state = CAP_STATE_WAITING;
			printf("save cancelled\n");
		}
		
	}else{
		printf("ERROR sorry - we weren't capturing!!!!!\n");
	}
	
}
bool mjpeg_decoder_t::decode_complete(void const *&y, void const *&u, void const *&v, void *&opaque, unsigned &displayIdx, int &picType, bool &errors )
{
        displayIdx = 0 ;
	errors = false ;
	if( startedDecode_ && !vpu_IsBusy() ){
                DecOutputInfo outinfo = {0};
		RetCode ret = vpu_DecGetOutputInfo(handle_, &outinfo);
debugPrint("vpu_DecGetOutputInfo(%d): %d display, %d decode\n", ret, outinfo.indexFrameDisplay, outinfo.indexFrameDecoded);
		if (ret == RETCODE_SUCCESS) {
			startedDecode_ = false ;
			debugPrint("success %d\n", outinfo.decodingSuccess);
			debugPrint("indexFrame decoded %d (0x%x)\n", outinfo.indexFrameDecoded, outinfo.indexFrameDecoded);
			debugPrint("indexFrame display %d (0x%x)\n", outinfo.indexFrameDisplay, outinfo.indexFrameDisplay);
			debugPrint("picType %d\n", outinfo.picType);
			picType = outinfo.picType ;
			if( 0 != outinfo.numOfErrMBs) {
				debugPrint("%d errMBs\n", outinfo.numOfErrMBs);
				errors = true ;
			}
			debugPrint("qpInfo %p\n", outinfo.qpInfo);
			debugPrint("hscale %d\n", outinfo.hScaleFlag);
			debugPrint("vscale %d\n", outinfo.vScaleFlag);
			debugPrint("index rangemap %d\n", outinfo.indexFrameRangemap);
			debugPrint("prescan result %d\n", outinfo.prescanresult);
			debugPrint("picstruct %d\n", outinfo.pictureStructure);
			debugPrint("topfield first %d\n", outinfo.topFieldFirst);
			debugPrint("repeat first %d\n", outinfo.repeatFirstField);
			debugPrint("field seq %d\n", outinfo.fieldSequence);
			debugPrint("size %dx%d\n", outinfo.decPicWidth, outinfo.decPicHeight);
			debugPrint("nsps %d\n", outinfo.notSufficientPsBuffer);
			debugPrint("nsslice %d\n", outinfo.notSufficientSliceBuffer);
			debugPrint("success %d\n", outinfo.decodingSuccess);
			debugPrint("interlaced %d\n", outinfo.interlacedFrame);
			debugPrint("mp4packed %d\n", outinfo.mp4PackedPBframe);
			debugPrint("h264Npf %d\n", outinfo.h264Npf);
			debugPrint("prog/repeat %d\n", outinfo.progressiveFrame);
			debugPrint("crop %d:%d->%d:%d\n", outinfo.decPicCrop.left,outinfo.decPicCrop.top, outinfo.decPicCrop.right, outinfo.decPicCrop.bottom);
			if( (0 <= outinfo.indexFrameDisplay) && (fbcount > outinfo.indexFrameDisplay) ){
				unsigned mask = 1<<outinfo.indexFrameDisplay ;
				assert(0 != (decoder_fbs&mask));
				decoder_fbs &= ~mask ;
				assert(0 == (app_fbs & mask));
				app_fbs |= mask ;

				frame_buf *pfb = pfbpool+outinfo.indexFrameDisplay ;
				y = (void *)(pfb->addrY + pfb->desc.virt_uaddr - pfb->desc.phy_addr);
				u = (char *)y + ySize();
				v = (char *)u + uvSize();
                                displayIdx = outinfo.indexFrameDisplay ;
				debugPrint("returning display index %u:%p\n", displayIdx,y);
				return true ;
			} else {
				fprintf(stderr, "Invalid display fb index: %d\n", outinfo.indexFrameDisplay);
				startDecode();
			}
		} else {
			fprintf( stderr, "Error %d from vpu_DecGetOutputInfo\n", ret );
		}
	} else {
		debugPrint( "VPU is busy\n" );
                vpu_WaitForInt(0);
	}

	return false ;
}
bool mjpeg_decoder_t::fill_buf( void const *data, unsigned length, void *opaque )
{
	if( length < STREAM_BUF_SIZE ){
		memcpy((void *)virt_bsbuf_addr,data,length);
		numRead = length ;
		vpu_DecUpdateBitstreamBuffer(handle_,length);
debugPrint( "copied %u bytes, state == %d\n", length, state_ );
		if( INIT == state_ ) {
			RetCode ret;
			DecInitialInfo initinfo = {0};
			ret = vpu_DecGetInitialInfo(handle_, &initinfo);
debugPrint("vpu_DecGetInitialInfo: %d\n", ret);
			if (ret != RETCODE_SUCCESS) {
				fprintf(stderr, "vpu_DecGetInitialInfo failed %d\n", ret);
				return false ;
			}
			else {
				vpu_DecSetEscSeqInit(handle_, 0);
debugPrint("vpu_DecSetEscSeqInit(0): %d\n", ret);
				if (initinfo.streamInfoObtained) {
					printf( "have stream info\n" );
					printf("Decoder: width = %d, height = %d, fps = %lu, minfbcount = %u\n",
							initinfo.picWidth, initinfo.picHeight,
							initinfo.frameRateInfo,
							initinfo.minFrameBufferCount);
					assert(0 == fbcount);
					assert(0 == fb);
					assert(0 == pfbpool);
					fbcount = initinfo.minFrameBufferCount + 2 ;
					fb = (FrameBuffer *)calloc(fbcount, sizeof(fb[0]));
					if (fb == NULL) {
						fprintf(stderr,"Failed to allocate fb\n");
						return false ;
					}
					pfbpool = (frame_buf *)calloc(fbcount, sizeof(pfbpool[0]));
					if (pfbpool == NULL) {
						fprintf(stderr, "Failed to allocate pfbpool\n");
						return false ;
					}
printf("fb == %p, pfbpool == %p, malloc == %p\n", fb, pfbpool, malloc(0x10000) );
					w_ = initinfo.picWidth ;
					h_ = initinfo.picHeight ;
					ystride_ = (initinfo.picWidth + 15)&~15;
					uvstride_ = ((initinfo.picWidth/2)+15)&~15;
printf( "strides: %u/%u\n", ystride_, uvstride_ );
					unsigned paddedHeight = (h_+15)&~15 ; 		// Why???
					unsigned ySize = ystride_ * paddedHeight ;
					unsigned uvSize = uvstride_ * (paddedHeight/2);

					imgSize_ = paddedHeight*(ystride_+uvstride_);
printf( "imgSize == %u, ySize %u, uvSize %u\n", imgSize_, ySize, uvSize );
					imgSize_ += (ystride_*paddedHeight) / 4 ; 	// Why?
printf( "padded == %u\n", imgSize_ );

					for (unsigned i = 0; i < fbcount ; i++) {
                                                decoder_fbs |= (1 <<i);
						struct frame_buf *f = pfbpool + i ;
debugPrint( "pfbpool[%u] == %p\n", i, f);
						f->desc.size = imgSize_ ;
						int err = IOGetPhyMem(&f->desc);
						if (err) {
							printf("Frame buffer allocation failure: %d\n", err);
							return false ;
						}
						debugPrint( "allocated frame buffer %u == 0x%x\n", i, f->desc.phy_addr );
						f->addrY = f->desc.phy_addr;
						f->addrCb = f->addrY + ySize ;
						f->addrCr = f->addrCb + uvSize ;
						f->mvColBuf = f->addrCr + uvSize ;
						f->desc.virt_uaddr = IOGetVirtMem(&(f->desc));
						debugPrint( "virt == %p\n", f->desc.virt_uaddr );
						if (f->desc.virt_uaddr <= 0) {
							fprintf(stderr, "Error mapping frame buffer memory\n" );
							return false ;
						}

						fb[i].bufY = f->addrY;
						fb[i].bufCb = f->addrCb;
						fb[i].bufCr = f->addrCr;
						fb[i].bufMvCol = f->mvColBuf ;
					}
debugPrint( "allocated frame buffers\n" );
	for( unsigned i = 0 ; i < fbcount ; i++ ) {
		debugPrint("fb[%d].bufY = 0x%lx\n", i, fb[i].bufY );
		debugPrint("fb[%d].bufCb = 0x%lx\n", i, fb[i].bufCb );
		debugPrint("fb[%d].bufCr = 0x%lx\n", i, fb[i].bufCr );
		debugPrint("fb[%d].bufMvCol = 0x%lx\n", i, fb[i].bufMvCol );
	}
					DecBufInfo bufinfo = {0};
					ret = vpu_DecRegisterFrameBuffer(handle_, fb, fbcount, ystride_, &bufinfo);
debugPrint("vpu_DecRegisterFrameBuffer: %d, %u fbs, stride %u\n", ret, fbcount,ystride_);
					if (ret != RETCODE_SUCCESS) {
						fprintf(stderr,"Register frame buffer failed\n");
						return false ;
					}
debugPrint( "registered frame buffers\n");
					int rot_angle = 0 ;
					ret = vpu_DecGiveCommand(handle_, SET_ROTATION_ANGLE, &rot_angle);
debugPrint("vpu_DecGiveCommand: %d(SET_ROTATION_ANGLE)/%d, angle %d\n", SET_ROTATION_ANGLE,ret, rot_angle);
					if (ret != RETCODE_SUCCESS)
						fprintf(stderr,"rot_angle %d\n", ret);
					int mirror = 0 ;
					ret = vpu_DecGiveCommand(handle_, SET_MIRROR_DIRECTION,&mirror);
debugPrint("vpu_DecGiveCommand: %d(SET_MIRROR_DIRECTION)/%d, mirror %d\n", SET_MIRROR_DIRECTION,ret, mirror);
					if (ret != RETCODE_SUCCESS)
						fprintf(stderr,"mirror %d\n", ret);
					int rot_stride = ystride_ ;
					ret = vpu_DecGiveCommand(handle_, SET_ROTATOR_STRIDE, &rot_stride);
debugPrint("vpu_DecGiveCommand: %d(SET_ROTATOR_STRIDE)/%d, stride %d\n", SET_ROTATOR_STRIDE,ret, rot_stride);
					if (ret != RETCODE_SUCCESS)
						fprintf(stderr,"rotstride %d\n", ret);
					state_ = DECODING ;
debugPrint("before decode: image size %u, ySize %u, uvSize %u\n", yuvSize(), this->ySize(), this->uvSize() );
					startDecode();
				}
			}
		}
		return true ;
	}
	else
		return false ;
}