[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Keeping objects history in vector while maintaining current, which design ?

Posted on 2012-08-25
10
Medium Priority
?
311 Views
Last Modified: 2013-01-22
Hi,

There is a program that acquire and display video image from a file. In the display there is a keyboard callback function that depending on  which touch we press doing some stuff (e.g: when we press 'i' , program gives us the frame number of the current image).
Simply pressing 'n' does go to next frame in the video. The problem is that I can't go
to the previous  frame. So I try to found better way to implement an history of my objects, I think to use vector to store the objects so I can retrieve it by LIFO way.

Here is the code view of whet I want to do but is the design correct how can I implement it ?  So the vector is vectorInput in which I try to add pInput object.

I tried to do with vector but I am not sure if it is good to use memcpy with vector ?
Is it good to use linked list or circular buffer instead of vector ?

#ifdef _WIN32	//Windows
#include <windows.h>
#include <conio.h> // _getch
#else			//Linux
#include <ncurses.h>
#include <stdlib.h>
#endif

#include <stdio.h>
#include <string.h>

#include <stdlib.h>
#include "dirent.h"
#include <string>
#include <iostream>
#include <fstream>

#include <vector> //here

#include "prj_video_inout.h"
#include "prj_display.h"

using namespace std;

//				Variables
CPrj_video_inoutDll	VideoInOutDll;
CPrj_display_Dll	DisplayDll;
CPrj_cimageDll	CImgDll;

//              Class project
class	ExploreProject
{
	public:
		ExploreProject()
		{
			pInput	= NULL;
			pImage	= NULL;
			sFile	= NULL;
			//vectorInput = NULL
			vec_history =100; //here
			//vectorInput.size()
			memcpy(&(vectorInput)[0], NULL,vec_history ); //here
		}

		~ExploreProject()
		{
			Close ();
		}

		bool	Load (char *video_file)
		{
			Close ();
			if (VideoInOutDll.func_open_video_input (video_file, &pInput) != 0)
				return false;

			sFile = strdup (video_file);

			DisplayDll.func_initwindow (sFile);
			Display ();

			vectorInput.reserve(vec_history); //here
			return true;
		}

		void	TimeToString (char *buff, __int64 ms)
		{
			int secs = ms / 1000;
			ms %= 1000;
			int mins = secs / 60;
			secs %= 60;
			int hours = mins / 60;
			mins %= 60;

			sprintf (buff, "%d:%02d:%02d:%03d", hours, mins, secs, ms);
		}
		
		void	Display ()
		{
			if (!pInput || !sFile)
				return;

			UpdateImage ();

			char	buff_time[64];
			TimeToString (buff_time, pInput->GetFrameTime ());

			CImgDrawRGB_Int*	draw = NULL;
			if (CImgDll.func_create_obj_draw_rgb (&draw, pImage) == 0)
			{
				draw->draw_text_filled(2, 2, buff_time, 255, 0, 0, 0, 0, 0);
				if (pCurrentEvent)
				{
					draw->draw_text_filled(2, 18, pCurrentEvent, 255, 0, 0, 0, 0, 0);
				}
				CImgDll.func_destroy_obj_draw_rgb (&draw);
			}
			DisplayDll.func_showCImageRGB (sFile, pImage, 0);
		}
		
		bool	KeyCommand (int key)
		{
			if (!pInput || !sFile)
				return true;

			if (key >= 'A' && key <= 'Z')
			{
				key-= 'A';
				key+= 'a';
			}

			switch (key)
			{
				case 'i':
				{
					iCurrentEventBeginTS = pInput->GetFrameTime ();
				}
				break;
				case 'p':
				{
					__int64	frame_num = pInput->GetFrameNumber	();
					if (frame_num)
					{
					    // PREVIOUS FUNCTION FAILS 
						/*
						pInput->SeekToFrame (frame_num-comp_fps);//-1 or -1 sec of frame
						DisplayDll.func_wait_key (30);
						*/
						
						//HERE TEST TO READ PREVIOUS HISTORY
						//*pInput=vectorInput[vec_history-comp_fps]; //comp error
						//memcpy(pInput,vectorInput[vec_history-comp_fps],sizeof(vectorInput));//crash
						//*pInput=*vectorInput[vec_history-comp_fps];
						pInput=*vectorInput.begin();
						//memcpy((void*)&pInput,(const void*)vectorInput[vec_history-comp_fps],sizeof(vectorInput));// crash
						DisplayDll.func_wait_key (30);						
					}
				}
				break;
				case 'n':
				{
					pInput->GetNext ();
					DisplayDll.func_wait_key (30);				
				}
				break;

				case 'q':
				{
					return false;
				}
				break;
			}

			Display ();
			return true;
		}

				void	Close ()
		{
			if (pInput)
			{
				VideoInOutDll.func_close_video_input (&pInput);
				pInput = NULL;
			}

			if (sFile)
			{
				DisplayDll.func_destwindow (sFile);
				free (sFile);
			}
		}
				
	private:
		PrjVideoInOut_int*	pInput;
		char*		sFile;
		char*		pCurrentEvent;
		CImgRGB*	pImage;
		__int64		iCurrentEventBeginTS;

	        //new history for previsous frames
		int 		vec_history;
		vector<PrjVideoInOut_int*> vectorInput;

		void	UpdateImage ()
		{
			CImgRGB*	current_image = pInput->GetImageRGB ();
			if (!current_image)
				return;

			bool	need_image = true;
			if (pImage)
			{
				if (pImage->get_img_width() == current_image->get_img_width ())
				{
					if (pImage->get_img_height() == current_image->get_img_height())
						need_image = false;
				}
			}

			if (need_image)
			{
				if (pImage)
				{
					CImgDll.func_destroy_obj_image_rgb (&pImage);
					pImage = NULL;
				}

				pImage = current_image->clone_me ();
				CImgDll.func_swap_r_to_b_color (pImage);
				return;
			}

			memcpy (pImage->get_img_data(), current_image->get_img_data(), current_image->get_img_width()*current_image->get_img_height()*3);
			CImgDll.func_swap_r_to_b_color (pImage);
			
			//here
			if((int)vectorInput.size()>=vec_history) 
				vectorInput.erase(vectorInput.begin());
			vectorInput.push_back(pInput);
		}
		
};
		
		
int main(int argc, char* argv[])
{

	ExploreProject	project;

	if (project.Load (argv[1]) != true)
	{
		printf ("Failed to load video file %s\n", argv[1]);
		return -1;
	}

	while (project.KeyCommand (DisplayDll.func_wait_key (0)))
	{
	}

	return 0;
}

Open in new window



My questions, is it good to:
To use separetly pInput and vectorInput and use only vectorInput when I press 'p'  in case 'p' of Keycommand function and for example get info of the previous frame number by pressing 'i' ?

Or Maybe to copy vectorInput in the  pInput  object and use this object, in this case it will be more difficult to design code but  use only one current object that seems more professional?


Thank you
0
Comment
Question by:Develprog
  • 4
  • 4
9 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 38332754
'memcpy()' should be OK for that purpose, but shouldn't that be

memcpy(pInput,vectorInput[frame_num - 1],image_size);

Open in new window


(with 'image_size' being the actual size of the image data)?
0
 

Author Comment

by:Develprog
ID: 38332836
Hi,

You mean in this part of code ?
	case 'p':
				{
					__int64	frame_num = pInput->GetFrameNumber	();
					if (frame_num)
					{
					    // PREVIOUS FUNCTION FAILS 
						/*
						pInput->SeekToFrame (frame_num-comp_fps);//-1 or -1 sec of frame
						DisplayDll.func_wait_key (30);
						*/
						
						//HERE TEST TO READ PREVIOUS HISTORY
                                               memcpy(pInput,vectorInput[frame_num - 1],sizeof(vectorInput));
						DisplayDll.func_wait_key (30);						
					}
				}

Open in new window


But  pInput object contain all needed data ( image, image frame number, ...)
So the idea is to copy all the object with all datas to get back the frame number of
previous  object (image)

Perhaps replace sizeof by somethin else ?

But the main problem come with the fact that when pInput receive his previous object is it really well stored so in UpdateImage() we can find previous data ?

 Thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 38332983
Yes, that's what I meant. Does 'PrjVideoInOut_int' contain a field that let's you determine the size of each entry in the vector? If so, that's what you need here.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:Develprog
ID: 38333170
Unfortunatly no,

I did in constructor():
      memcpy(&(vectorInput)[0], NULL,vec_history );

in load():
       vectorInput.reserve(vec_history); //here

And at each loop in UpdateImage():
                  if((int)vectorInput.size()>=vec_history)
                        vectorInput.erase(vectorInput.begin());
                  vectorInput.push_back(pInput);

Is the design correct ?

Thank you
0
 
LVL 86

Accepted Solution

by:
jkr earned 2000 total points
ID: 38333206
Hm you seem to be using

memcpy (pImage->get_img_data(), current_image->get_img_data(), current_image->get_img_width()*current_image->get_img_height()*3);

Open in new window


to store the image. So, instead of using a

vector<PrjVideoInOut_int*> vectorInput;

Open in new window


why don't you use something like

struct MyImage {

  PrjVideoInOut_int* pImg;
  size_t szImgSize;
};
vector<MyImage> vectorInput;

Open in new window


so that you then can use

memcpy(pInput,vectorInput[frame_num - 1].pImg,vectorInput[frame_num - 1].szImgSize);
                                            

Open in new window

0
 

Author Comment

by:Develprog
ID: 38334441
Yes good but I must indeed to fill szImgSize but I can't get information about the size of
a PrjVideoInOut_int object.
0
 
LVL 86

Expert Comment

by:jkr
ID: 38334513
Since the size info always is associated with each entry, you always will have that information ready, that should not be a problem. All you do is have to store it in the struct together with the pointer before adding the struct to the vector.
0
 

Author Comment

by:Develprog
ID: 38373988
Hi,

Sorry for late, Thank you jkr, I'll test it.
0
 
LVL 53

Expert Comment

by:Dhaest
ID: 38804712
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
When you discover the power of the R programming language, you are going to wonder how you ever lived without it! Learn why the language merits a place in your programming arsenal.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question