From 9d19cbdcad5bffe23bc0274fdb50895fa06f0fe0 Mon Sep 17 00:00:00 2001 From: Ewing Kang Date: Sat, 13 Feb 2021 13:16:10 +0800 Subject: [PATCH] Add cabability to retrieve raw frame hardware STC timestamp * Add definition for setting timestamp format * Modify data structure to contain timestamp info * Add interface to retrieve timestamp --- src/private/private_impl.cpp | 43 +++++++++++++++++++++++++++++++----- src/private/private_impl.h | 19 ++++++++++++---- src/private/private_types.h | 3 ++- src/raspicam.cpp | 15 ++++++++++++- src/raspicam.h | 10 ++++++++- src/raspicamtypes.h | 7 ++++++ utils/raspicam_test.cpp | 8 +++++-- 7 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/private/private_impl.cpp b/src/private/private_impl.cpp index 6d9b64f..4993b67 100644 --- a/src/private/private_impl.cpp +++ b/src/private/private_impl.cpp @@ -68,9 +68,9 @@ namespace raspicam { // Default everything to zero memset ( &State, 0, sizeof ( RASPIVID_STATE ) ); - State.framerate = 30; - State.width = 1280; // use a multiple of 320 (640, 1280) - State.height = 960; // use a multiple of 240 (480, 960) + State.framerate = 30; + State.width = 1280; // use a multiple of 320 (640, 1280) + State.height = 960; // use a multiple of 240 (480, 960) State.sharpness = 0; State.contrast = 0; State.brightness = 50; @@ -93,6 +93,7 @@ namespace raspicam { State.shutterSpeed=0;//auto State.awbg_red=1.0; State.awbg_blue=1.0; + State.ptc_tsMode = RASPICAM_TIMESTAMP_MODE_RAW_STC; } bool Private_Impl::open ( bool StartCapture ) { @@ -173,7 +174,12 @@ namespace raspicam { /** * */ - void Private_Impl::retrieve ( unsigned char *data,RASPICAM_FORMAT type ) { + void Private_Impl::retrieve ( unsigned char *data, RASPICAM_FORMAT type ) { + int64_t ts; + retrieve(&ts, data, type); + } + void Private_Impl::retrieve ( int64_t *timestamp, unsigned char *data, RASPICAM_FORMAT type ) { + (*timestamp) = 0; if ( callback_data._buffData.size==0 ) return; if ( type!=RASPICAM_FORMAT_IGNORE ) { cerr<<__FILE__<<":"<<__LINE__<<" :Private_Impl::retrieve type is not RASPICAM_FORMAT_IGNORE as it should be"<es->video.width*3;//line stride } } - + (*timestamp) = callback_data.timestamp; } unsigned char *Private_Impl::getImageBufferData() const{ return callback_data._buffData.data; } + /** + * Returns the timestamp of the image that is in the current internal buffer + */ + int64_t Private_Impl::getTimeStamp() const { + return callback_data.timestamp; + } size_t Private_Impl::getImageBufferSize() const{ return getImageTypeSize ( getFormat() ); @@ -288,7 +300,7 @@ namespace raspicam { cam_config.num_preview_video_frames = 3; cam_config.stills_capture_circular_buffer_height = 0; cam_config.fast_preview_resume = 0; - cam_config.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC; + cam_config.use_stc_timestamp = convertTimestampMode(state->ptc_tsMode); mmal_port_parameter_set ( camera->control, &cam_config.hdr ); // Set the encode format on the video port @@ -500,6 +512,7 @@ namespace raspicam { memcpy ( pData->_buffData.data,buffer->data,buffer->length ); pData->wantToGrab =false; hasGrabbed=true; + pData->timestamp = buffer->pts; mmal_buffer_header_mem_unlock ( buffer ); } } @@ -720,6 +733,19 @@ namespace raspicam { return MMAL_PARAM_AWBMODE_AUTO; } } + MMAL_PARAMETER_CAMERA_CONFIG_TIMESTAMP_MODE_T Private_Impl::convertTimestampMode ( RASPICAM_TIMESTAMP_MODE tsMode ) + { + switch(tsMode) { + case RASPICAM_TIMESTAMP_MODE_ZERO: + return MMAL_PARAM_TIMESTAMP_MODE_ZERO; + case RASPICAM_TIMESTAMP_MODE_RAW_STC: + return MMAL_PARAM_TIMESTAMP_MODE_RAW_STC; + case RASPICAM_TIMESTAMP_MODE_RESET_STC: + return MMAL_PARAM_TIMESTAMP_MODE_RESET_STC; + default: + return MMAL_PARAM_TIMESTAMP_MODE_RAW_STC; + } + } MMAL_PARAM_IMAGEFX_T Private_Impl::convertImageEffect ( RASPICAM_IMAGE_EFFECT imageEffect ) { switch ( imageEffect ) { @@ -771,6 +797,11 @@ namespace raspicam { void Private_Impl::setFrameRate ( unsigned int frame_rate ) { State.framerate = frame_rate; } + + void Private_Impl::setTimestampMode(RASPICAM_TIMESTAMP_MODE tsMode) + { + State.ptc_tsMode = tsMode; + } int Private_Impl::convertFormat ( RASPICAM_FORMAT fmt ) { switch ( fmt ) { diff --git a/src/private/private_impl.h b/src/private/private_impl.h index 7f71780..5a34e3d 100644 --- a/src/private/private_impl.h +++ b/src/private/private_impl.h @@ -77,7 +77,7 @@ namespace raspicam { ThreadCondition Thcond; bool wantToGrab; membuf _buffData; - + int64_t timestamp; }; public: @@ -112,6 +112,7 @@ namespace raspicam { * You can use getFormat to know the current format */ void retrieve ( unsigned char *data,RASPICAM_FORMAT type=RASPICAM_FORMAT_IGNORE ); + void retrieve ( int64_t *timestamp, unsigned char *data,RASPICAM_FORMAT type=RASPICAM_FORMAT_IGNORE ); /**Alternative to retrieve. Returns a pointer to the original image data buffer. * Be careful, if you call grab(), this will be rewritten with the new data */ @@ -120,7 +121,11 @@ namespace raspicam { * Returns the size of the buffer returned in getImagePtr. If is like calling getImageTypeSize(getFormat()). Just for dummies :P */ size_t getImageBufferSize() const; - + /** + * Returns the timestamp of the image that is in the current internal buffer + */ + int64_t getTimeStamp() const; + /** Stops camera and free resources */ void release(); @@ -141,7 +146,8 @@ namespace raspicam { void setExposureCompensation ( int val ); //-10,10 void setAWB ( RASPICAM_AWB awb ); void setAWB_RB ( float red,float blue );//ranges [0,1] - void setFrameRate ( unsigned int frame_rate ) ; + void setFrameRate ( unsigned int frame_rate ); + void setTimestampMode(RASPICAM_TIMESTAMP_MODE tsMode); void setImageEffect ( RASPICAM_IMAGE_EFFECT imageEffect ); void setMetering ( RASPICAM_METERING metering ); @@ -203,6 +209,10 @@ namespace raspicam { { return State.rpc_awbMode; } + RASPICAM_TIMESTAMP_MODE getTimestampMode() const + { + return State.ptc_tsMode; + } float getAWBG_red(){return State.awbg_red;} @@ -263,11 +273,12 @@ namespace raspicam { MMAL_PARAM_AWBMODE_T convertAWB ( RASPICAM_AWB awb ) ; MMAL_PARAM_IMAGEFX_T convertImageEffect ( RASPICAM_IMAGE_EFFECT imageEffect ) ; MMAL_PARAM_EXPOSUREMETERINGMODE_T convertMetering ( RASPICAM_METERING metering ) ; + MMAL_PARAMETER_CAMERA_CONFIG_TIMESTAMP_MODE_T convertTimestampMode ( RASPICAM_TIMESTAMP_MODE tsMode ); int convertFormat ( RASPICAM_FORMAT fmt ) ; //Color conversion - void convertBGR2RGB(unsigned char * in_bgr,unsigned char * out_rgb,int size); + void convertBGR2RGB(unsigned char * in_bgr,unsigned char * out_rgb,int size); float VIDEO_FRAME_RATE_NUM; RASPIVID_STATE State; MMAL_STATUS_T status; diff --git a/src/private/private_types.h b/src/private/private_types.h index 07d1a98..4f244bc 100644 --- a/src/private/private_types.h +++ b/src/private/private_types.h @@ -72,11 +72,12 @@ namespace raspicam { bool videoStabilisation; /// 0 or 1 (false or true) int exposureCompensation; /// -10 to +10 ? int shutterSpeed; - RASPICAM_FORMAT captureFtm; + RASPICAM_FORMAT captureFtm; RASPICAM_EXPOSURE rpc_exposureMode; RASPICAM_METERING rpc_exposureMeterMode; RASPICAM_AWB rpc_awbMode; RASPICAM_IMAGE_EFFECT rpc_imageEffect; + RASPICAM_TIMESTAMP_MODE ptc_tsMode; MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imageEffectsParameters; MMAL_PARAM_COLOURFX_T colourEffects; int rotation; /// 0-359 diff --git a/src/raspicam.cpp b/src/raspicam.cpp index 4cc27a4..f9a153b 100644 --- a/src/raspicam.cpp +++ b/src/raspicam.cpp @@ -63,8 +63,12 @@ namespace raspicam { void RaspiCam::retrieve ( unsigned char *data,RASPICAM_FORMAT type ) { _impl->retrieve ( data,type ); } + void RaspiCam::retrieve ( int64_t *timestamp, unsigned char *data,RASPICAM_FORMAT type ) { + _impl->retrieve ( timestamp,data,type ); + } unsigned char *RaspiCam::getImageBufferData() const{return _impl->getImageBufferData();} size_t RaspiCam::getImageBufferSize() const{return _impl->getImageBufferSize();} + int64_t RaspiCam::getTimeStamp() const { return _impl->getTimeStamp();} size_t RaspiCam::getImageTypeSize ( RASPICAM_FORMAT type ) const{return _impl->getImageTypeSize ( type );} @@ -134,7 +138,12 @@ namespace raspicam { void RaspiCam::setVerticalFlip ( bool vFlip ) { _impl->setVerticalFlip ( vFlip ); } - void RaspiCam::setFrameRate( unsigned int fr) { _impl->setFrameRate(fr);} + void RaspiCam::setFrameRate( unsigned int fr) { + _impl->setFrameRate(fr); + } + void RaspiCam::setTimestampMode(RASPICAM_TIMESTAMP_MODE tsMode) { + _impl->setTimestampMode(tsMode); + }; RASPICAM_FORMAT RaspiCam::getFormat()const{return _impl->getFormat( ); } @@ -145,6 +154,10 @@ namespace raspicam { int RaspiCam::getISO() const{return _impl->getISO() ;} unsigned int RaspiCam::getShutterSpeed() const{return _impl->getShutterSpeed();}//return _impl->getShutterSpeed();} unsigned int RaspiCam::getFrameRate()const{return _impl->getFrameRate();} + RASPICAM_TIMESTAMP_MODE RaspiCam::getTimestampMode() const { + return _impl->getTimestampMode(); + } + int RaspiCam::getSharpness() const{return _impl->getSharpness() ;} int RaspiCam::getContrast() const{return _impl->getContrast() ;} diff --git a/src/raspicam.h b/src/raspicam.h index d7cfce3..60ac645 100644 --- a/src/raspicam.h +++ b/src/raspicam.h @@ -77,6 +77,7 @@ namespace raspicam { * You can use getFormat() to know the current format */ void retrieve ( unsigned char *data,RASPICAM_FORMAT type=RASPICAM_FORMAT_IGNORE ); + void retrieve ( int64_t *timestamp, unsigned char *data,RASPICAM_FORMAT type=RASPICAM_FORMAT_IGNORE ); /**Alternative to retrieve. Returns a pointer to the original image data buffer (which is in getFormat() format). * * Be careful, if you call grab(), this will be rewritten with the new data @@ -86,6 +87,10 @@ namespace raspicam { * Returns the size of the images captured. */ size_t getImageBufferSize() const; + /** + * Returns the timestamp of the image that is in the current internal buffer + */ + int64_t getTimeStamp() const; /** Stops camera and free resources @@ -139,6 +144,8 @@ namespace raspicam { void setHorizontalFlip ( bool hFlip ); void setVerticalFlip ( bool vFlip ); void setFrameRate(unsigned int fr); + void setTimestampMode(RASPICAM_TIMESTAMP_MODE tsMode); + //Accessors RASPICAM_FORMAT getFormat() const; unsigned int getWidth() const; @@ -158,7 +165,8 @@ namespace raspicam { RASPICAM_METERING getMetering() const; bool isHorizontallyFlipped() const ; bool isVerticallyFlipped() const ; - unsigned int getFrameRate()const; + unsigned int getFrameRate() const; + RASPICAM_TIMESTAMP_MODE getTimestampMode() const; /** Returns an id of the camera. We assume the camera id is the one of the raspberry *the id is obtained using raspberry serial number obtained in /proc/cpuinfo diff --git a/src/raspicamtypes.h b/src/raspicamtypes.h index 3d4479e..b577e26 100644 --- a/src/raspicamtypes.h +++ b/src/raspicamtypes.h @@ -127,6 +127,13 @@ namespace raspicam { RASPICAM_ENCODING_RGB } RASPICAM_ENCODING; + typedef enum RASPICAM_TIMESTAMP_MODE { + RASPICAM_TIMESTAMP_MODE_ZERO, /* Always timestamp frames as 0 */ + RASPICAM_TIMESTAMP_MODE_RAW_STC, /* Use the raw STC value for the frame timestamp */ + RASPICAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp but subtract the timestamp + * of the first frame sent to give a zero based timestamp. */ + } RASPICAM_TIMESTAMP_MODE; + }; #endif diff --git a/utils/raspicam_test.cpp b/utils/raspicam_test.cpp index b505f3e..b6f072d 100644 --- a/utils/raspicam_test.cpp +++ b/utils/raspicam_test.cpp @@ -201,6 +201,7 @@ int main ( int argc,char **argv ) { } cout<<"Connected to camera ="<0 ) { //save image if not in inifite loop std::stringstream fn; fn<<"image";