int RemoteCameraHttp::Capture( Image &image ) { int content_length = GetResponse(); if ( content_length == 0 ) { Warning( "Unable to capture image, retrying" ); return( 1 ); } if ( content_length < 0 ) { Error( "Unable to get response" ); Disconnect(); return( -1 ); } switch( format ) { case JPEG : { if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) { Error( "Unable to decode jpeg" ); Disconnect(); return( -1 ); } break; } case X_RGB : { if ( content_length != image.Size() ) { Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length ); Disconnect(); return( -1 ); } image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); break; } case X_RGBZ : { if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) { Error( "Unable to unzip RGB image" ); Disconnect(); return( -1 ); } image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); break; } default : { Error( "Unexpected image format encountered" ); Disconnect(); return( -1 ); } } return( 0 ); }
int FfmpegCamera::Capture( Image &image ) { static int frameCount = 0; AVPacket packet; int frameComplete = false; while ( !frameComplete && (av_read_frame( mFormatContext, &packet ) >= 0) ) { Debug( 5, "Got packet from stream %d", packet.stream_index ); if ( packet.stream_index == mVideoStreamId ) { if ( avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size) < 0 ) Fatal( "Unable to decode frame at frame %d", frameCount ); Debug( 3, "Decoded video packet at frame %d", frameCount ); if ( frameComplete ) { Debug( 1, "Got frame %d", frameCount ); #if HAVE_LIBSWSCALE if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) Fatal( "Unable to convert raw format %d to RGB at frame %d", mCodecContext->pix_fmt, frameCount ); #else // HAVE_LIBSWSCALE Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); #endif // HAVE_LIBSWSCALE image.Assign( mCodecContext->width, mCodecContext->height, colours, (unsigned char *)mFrame->data[0] ); frameCount++; } } av_free_packet( &packet ); } return (0); }
// Should not return -1 as cancels capture. Always wait for image if available. int LibvlcCamera::Capture( Image &image ) { while(!mLibvlcData.newImage.getValueImmediate()) mLibvlcData.newImage.getUpdatedValue(1); mLibvlcData.mutex.lock(); image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp); mLibvlcData.newImage.setValueImmediate(false); mLibvlcData.mutex.unlock(); return (0); }
// Should not return -1 as cancels capture. Always wait for image if available. int LibvlcCamera::Capture(Image &image) { // newImage is a mutex/condition based flag to tell us when there is an image available while( !mLibvlcData.newImage.getValueImmediate() ) { if (zm_terminate) return 0; mLibvlcData.newImage.getUpdatedValue(1); } mLibvlcData.mutex.lock(); image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp); mLibvlcData.newImage.setValueImmediate(false); mLibvlcData.mutex.unlock(); return 1; }
Image *StreamBase::prepareImage( Image *image ) { static int last_scale = 0; static int last_zoom = 0; static int last_x = 0; static int last_y = 0; if ( !last_scale ) last_scale = scale; if ( !last_zoom ) last_zoom = zoom; // Do not bother to scale zoomed in images, just crop them and let the browser scale // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. bool optimisedScaling = false; bool image_copied = false; int mag = (scale * zoom) / ZM_SCALE_BASE; int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag ); int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag ); int base_image_width = image->Width(), base_image_height = image->Height(); Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height ); int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height ); int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height ); int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height ); int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height ); int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height ); int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height ); int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height ); int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height ); if ( mag != ZM_SCALE_BASE ) { if ( act_mag != ZM_SCALE_BASE ) { Debug( 3, "Magnifying by %d", mag ); if ( !image_copied ) { static Image copy_image; copy_image.Assign( *image ); image = ©_image; image_copied = true; } image->Scale( mag ); } } Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() ); if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height ) { static Box last_crop; if ( mag != last_mag || x != last_x || y != last_y ) { Debug( 3, "Got click at %d,%d x %d", x, y, mag ); //if ( !last_mag ) //last_mag = mag; if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) last_crop = Box(); Debug( 3, "Recalculating crop" ); // Recalculate crop parameters, as %ges int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image click_x += ( x * 100 ) / last_virt_image_width; int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image click_y += ( y * 100 ) / last_virt_image_height; Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); // Convert the click locations to the current image pixels click_x = ( click_x * act_image_width ) / 100; click_y = ( click_y * act_image_height ) / 100; Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); int lo_x = click_x - (send_image_width/2); if ( lo_x < 0 ) lo_x = 0; int hi_x = lo_x + (send_image_width-1); if ( hi_x >= act_image_width ) { hi_x = act_image_width - 1; lo_x = hi_x - (send_image_width - 1); } int lo_y = click_y - (send_image_height/2); if ( lo_y < 0 ) lo_y = 0; int hi_y = lo_y + (send_image_height-1); if ( hi_y >= act_image_height ) { hi_y = act_image_height - 1; lo_y = hi_y - (send_image_height - 1); } last_crop = Box( lo_x, lo_y, hi_x, hi_y ); } Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() ); if ( !image_copied ) { static Image copy_image; copy_image.Assign( *image ); image = ©_image; image_copied = true; } image->Crop( last_crop ); } last_scale = scale; last_zoom = zoom; last_x = x; last_y = y; return( image ); }
int RemoteCameraRtsp::Capture( Image &image ) { while ( true ) { buffer.clear(); if ( !rtspThread->isRunning() ) break; //if ( rtspThread->stopped() ) //break; if ( rtspThread->getFrame( buffer ) ) { Debug( 3, "Read frame %d bytes", buffer.size() ); Debug( 4, "Address %p", buffer.head() ); Hexdump( 4, buffer.head(), 16 ); static AVFrame *tmp_picture = NULL; if ( !tmp_picture ) { //if ( c->pix_fmt != pf ) //{ tmp_picture = avcodec_alloc_frame(); if ( !tmp_picture ) { Panic( "Could not allocate temporary opicture" ); } int size = avpicture_get_size( PIX_FMT_RGB24, width, height); uint8_t *tmp_picture_buf = (uint8_t *)malloc(size); if (!tmp_picture_buf) { av_free( tmp_picture ); Panic( "Could not allocate temporary opicture" ); } avpicture_fill( (AVPicture *)tmp_picture, tmp_picture_buf, PIX_FMT_RGB24, width, height ); //} } if ( !buffer.size() ) return( -1 ); AVPacket packet; av_init_packet( &packet ); int initialFrameCount = frameCount; while ( buffer.size() > 0 ) { int got_picture = false; packet.data = buffer.head(); packet.size = buffer.size(); int len = avcodec_decode_video2( codecContext, picture, &got_picture, &packet ); if ( len < 0 ) { if ( frameCount > initialFrameCount ) { // Decoded at least one frame return( 0 ); } Error( "Error while decoding frame %d", frameCount ); Hexdump( ZM_DBG_ERR, buffer.head(), buffer.size()>256?256:buffer.size() ); buffer.clear(); continue; //return( -1 ); } Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() ); //if ( buffer.size() < 400 ) //Hexdump( 0, buffer.head(), buffer.size() ); if ( got_picture ) { /* the picture is allocated by the decoder. no need to free it */ Debug( 1, "Got picture %d", frameCount ); static struct SwsContext *img_convert_ctx = 0; if ( !img_convert_ctx ) { img_convert_ctx = sws_getCachedContext( NULL, codecContext->width, codecContext->height, codecContext->pix_fmt, width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL ); if ( !img_convert_ctx ) Panic( "Unable to initialise image scaling context" ); } sws_scale( img_convert_ctx, picture->data, picture->linesize, 0, height, tmp_picture->data, tmp_picture->linesize ); image.Assign( width, height, colours, tmp_picture->data[0] ); frameCount++; return( 0 ); } else { Warning( "Unable to get picture from frame" ); } buffer -= len; } } } return( -1 ); }