C++ Windows RPC how to define the MIDL can transmit null terminated char array - c++

My project is use C++ Windows RPC to upload image(512*512) from client to server. I do not use WIN RPC before, So I tried some examples include send basic "Hello world" Message to server, but the huge issue is the function can't send unsigned char* include '\0'. I mean there are a lot of '\0' characters in the char array, they can't send to the server.
I think it is because I defined wrong MIDL function.
I tried:
void Output(
[in, out, size_is(1048576), string] unsigned char* szString);
another one
void Output1(
[in, length_is(1048576)] unsigned char[]);
But both can't work.
I use opencv3.2 to read image to Mat structure, and it can get Mat data and use memcpy to copy the Mat.data then create a new image in local client. But when I send Mat.data to server, the first of characters in the Mat.data is '\0'. All the Mat.data can't send to server.
My Client core code(It has include all require header) is
Mat I = imread("U:\\normal.jpg", IMREAD_ANYDEPTH);
if (I.empty())
{
std::cout << "!!! Failed imread(): image not found" << std::endl;
// don't let the execution continue, else imshow() will crash.
}
if (!I.data) {
std::cout << "can't open or find image" << std::endl;
//return -1;
}
I.convertTo(I, CV_32F);
I = (I.reshape(0, 1)); // to make it continuous
char tr[512*512*4];
memcpy_s(tr, 512 * 512 * 4, I.data, 512*512 * 4);
//snprintf(tr, 512*512*4,"%s", I.data);
Mat out = Mat(512,512, CV_32F, &tr[0]);
namedWindow("Display window", CV_WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", out);
waitKey(5000);
...
RpcTryExcept
{
std::clog << "Calling Open" << std::endl;
output((unsigned char* )tr); // process the function, send data to server
//output1((unsigned char* )tr);
}

Related

SDL only making beeping noises instead of the actual audio file

I recently managed to get past the errors of using SDL for sound.
Now that it's running and I'm not running into errors, my program is only playing beeping noises instead of the file I've provided.
I want the program to play the .wav file I'm passing to the SDL_LoadWAV.
I've tried with two different .wav files of different length and size, and checked the header files to find comments and tips on what format is required for the SDL to play the .wav file, haven't gotten anywhere with either of it.
The myAudioCallback function is responsible for handling the SDL callback.
void myAudioCallback(void* userdata, Uint8* stream, int len)
{
AudioData* audio = (AudioData*)userdata;
if (audio->length == 0)
return;
Uint32 length = (Uint32)len;
length = (length > audio->length ? audio->length : length); // if length is more than the audio length, then set length to be the audio.length, if not, set it to be the length passed to the function
std::cout << "Audio Length " << audio->length << std::endl;
std::cout << "Audio Position " << audio->position << std::endl;
SDL_memcpy(stream, audio->position, length); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it
audio->position += length;
audio->length -= length;
}
My loadAudio function is responsible for loading the audio file and saving information about the audio file to the various variables I've declared in the .h (see further down for my .h)
void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file
{
SDL_Init(SDL_INIT_AUDIO); // loads the SDL to initialise audio
char* audioFile = "backgroundmusic.wav"; // a char pointer for the file path
// LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
if (SDL_LoadWAV(audioFile, &wavSpec, &wavStart, &wavLength) == NULL)
std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
else
std::cout << audioFile << " loaded" << std::endl;
}
The playAudio function is responsible for loading the audio device and playing the audio through the Audio device
void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device
{
audio.position = wavStart; // define where we start in the audio file
audio.length = wavLength; // define the length of the audio file
wavSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
wavSpec.userdata = &audio; // the userdata is the audio itself
audioDevice = SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE); // opens the audio device, also having it play the audio information found at memory address for wavspec
if (audioDevice == 0) {
std::cerr << SDL_GetError() << std::endl;
return; }
SDL_PauseAudioDevice(audioDevice, 0); // mildly confused by why they decided to call the function for starting to play audio for "PauseAudioDevice" but yeah. this plays audio.
}
Here's my .h. I've defined myAudioCallback outside of the class, since SDL doesn't like the additional hidden parameter of a member function
struct AudioData
{
Uint8* position;
Uint32 length;
};
void myAudioCallback(void* userdata, Uint8* stream, int len);
class mainEngineCW4 :
public BaseEngine
{
public:
void loadAudio();
void playAudio();
void endAudio();
private:
// variables and pointers for audio information
AudioData audio;
SDL_AudioSpec wavSpec;
SDL_AudioDeviceID audioDevice;
Uint8* wavStart;
Uint32 wavLength;
};
I've removed the other functions and variables that are irrelevant to the issue I'm having
My problem is that I want my program to play the audio file I pass in, not just beeping noises.
Any help is greatly appreciated
EDIT: I realised I'm crap at providing info and explanation to things, so I edited in more information, explanation and the header file. If there is anything else I can provide, please let me know
With the help of a friend, I managed to fix the issue.
It seems like SDL didn't like it when I passed
SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, SDL_AUDIO_ALLOW_ANY_CHANGE);
so instead, I passed
SDL_OpenAudioDevice(NULL, 0, &wavSpec, NULL, 0);
instead. This made the file play nicely, as well as having additional variables for the length and position of the audio file.
Another issue I ran into even after I got the file playing, was that the beeping was still playing with the audio file. I wasn't able to fix this directly myself, instead, when I cleaned the solution the day after, the beeping was gone, and the only thing playing was the audio file.
I've attached the code that works below.
In addition to the struct I created in the .h
struct AudioData
{
Uint8* position;
Uint32 length;
};
Defining the audio_position and audio_length as a global variable also helped in copying over information in the audio callback function.
static Uint8* audio_position;
static Uint32 audio_length;
void myAudioCallback(void* userdata, Uint8* stream, int len)
{
if (audio_length == 0)
return;
len = (len > audio_length ? audio_length : len); // if length is more than the audio length, then set length to be the audio.length, if not, set it to be the length passed to the function
SDL_memcpy(stream, audio_position, len); // audio callback is called by SDL, this ensures that the stream and data that is sent, is copied over to our struct, so we can use it and manipulate it
audio_position += len;
audio_length -= len;
}
For the load audio, I made sure that I actually load all the information that would be considered "loading", including storing the AudioSpec callback function, and setting the length and position of the audio file.
void mainEngineCW4::loadAudio() // this function is for the sole purpose of loading the .wav file
{
if (SDL_Init(SDL_INIT_AUDIO) < 0 || audioPlaying == true) // loads the SDL to initialise audio
return;
char* filePath = "backgroundmusic.wav"; // a char pointer for the file path
// LoadWAV loads the wav file, and by putting it in an if statement like this, we can simutaneously check if the result is null, meaning an error occured while loading it.
if (SDL_LoadWAV(filePath, &desiredSpec, &wavStart, &wavLength) == NULL)
std::cerr << "Error: file could not be loaded as an audio file." << std::endl;
else
std::cout << filePath << " loaded" << std::endl;
desiredSpec.callback = myAudioCallback; // the callback variable needs a function that its going to run to be able to call back the audio that is played. assigning the function name to the variable allows it to call that function when needed
desiredSpec.userdata = &audioInfo; // the userdata is the audio itself
audio_position = wavStart; // define where we start in the audio file
audio_length = wavLength; // define the length of the audio file
}
I also added a boolean to the class, so that when this returns true, it means that the audio has already been playing or has already been loaded, as to ensure SDL won't play the same thing simultaneously.
void mainEngineCW4::playAudio() // this function is for loading an audio device, and playing the audio through that device
{
if (audioPlaying == true)
return;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, NULL, 0); // opens the audio device, also having it play the audio information found at memory address for wavspec
if (audioDevice == 0)
{
std::cerr << SDL_GetError() << std::endl;
return;
}
SDL_PauseAudioDevice(audioDevice, 0); // mildly confused by why they decided to call the function for starting to play audio for "PauseAudioDevice" but yeah. this plays audio.
audioPlaying = true;
}
void mainEngineCW4::endAudio()
{
SDL_CloseAudioDevice(audioDevice);
SDL_FreeWAV(wavStart);
audioPlaying = false;
}

Receiving jpeg through socket and yet unable to display on Qt

I trying to send and receive jpeg images (image size around: 1kb) from my client socket. I have successfully send and receive the image data by checking the size of the data. However when I tried to past the image data to QByteArray and display on QImage, nothing was shown. The code below is a snippet of the receiving and displaying jpeg image.
Server.cpp
memcpy(&Rbuffer, ptr, msgCtl.iMsgLen - 8);
ptr += msgCtl.iMsgLen - 8;
cout << "Size of the image data recieve from the send buffer is " << sizeof(Rbuffer) << endl;
QByteArray ba = QByteArray::fromRawData(Rbuffer, sizeof(Rbuffer));
QBuffer qbuff(&ba);
qbuff.open(QIODevice::ReadOnly);
//QImageReader qimg ("C:\\test.jpg");
QImageReader qimg (&qbuff,"JPG");
qimg.setDecideFormatFromContent(true);
qimg.setDevice(&qbuff);
QImage img = qimg.read();
if (!img.isNull()){
cout << "no problem" << endl;
}
imageView->setPixmap(QPixmap::fromImage(img));
Hope someone could guide me on this. Thank you
On Windows, you have to copy the imageformats directory to your build directory.
eg.
C:\Qt\5.7\msvc2015_64\plugins\imageformats to my_build_dir\imageformats
Try this code:
QPixmap scaledPixmap = QPixmap::fromImage(image).scaled(
QSize(imageWidth, imageHeight),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
imageView->setScaledContents(false);
imageView->setPixmap(scaledPixmap);

copying char to QbyteArray with datastream contains some extra bytes

Overview of problem:
OS : Ubuntu
I am using qt utility to receive video data from remote machine( remote machine is using gstreamer to send live data) and write that data to port say 5000.
Port 5000 is already bind to another gstreamer utility. this utility listen to port 5000 and convert data into video streaming. Obviously things are not exactly working and I cant view video. So I have two questions:
1) With Qt utility , is it legal to write to port 5000 although port is bind to gstreamer utility.
2) I am using 3rd party library and its api to receive data from external source. The data get stored in array of characters. If I convert that into qbytearray then qbytearray has same size as char buffer. example
rc = zco_receive_source(sdr, &reader, bytesToRead, buffer); // this is 3rd part function
qDebug() << " copy buffer size =" << rc; // genrally this size is 1412
QByteArray msgRecvd;
msgRecvd = QByteArray(reinterpret_cast<char*>(buffer), rc);
if(! msgRecvd.isEmpty() )
{
qDebug() << " size of msgRecv =" << msgRecvd.size();// again 1412
udpSock->writeDatagram( msgRecvd, QHostAddress::LocalHost, 5000 );
}
But if I use QDataStream then QbyteArray got 4 extra bytes. code shown below
rc = zco_receive_source(sdr, &reader, bytesToRead, buffer); // this is 3rd part function
qDebug() << " copy buffer size =" << rc; // genrally this size is 1412
QByteArray msgRecvd;
QDataStream dataStream( &msgRecvd, QIODevice::WriteOnly );
dataStream.writeBytes( ( const char* )buffer, rc );
if(! msgRecvd.isEmpty() )
{
qDebug() << " size of msgRecv =" << msgRecvd.size();// got 4 extra bytes .. size is 1415. why ???
udpSock->writeDatagram( msgRecvd, QHostAddress::LocalHost, 5000 );
}
I want to know why QbyteArray got extra character and do I need to serialise data to forward it to port 5000?
Answering on second question:
Try QDataStream::writeRawData().
Form Qt docs:
QDataStream & QDataStream::writeBytes(const char * s, uint len)
Writes the length specifier len and the buffer s to the stream and returns a reference to the stream.
The len is serialized as a quint32, followed by len bytes from s. Note that the data is not encoded.

OpenCV edit captured ip camera

Can I use OpenCV to edit video captured from Ip camera with Dahua SDK?
Here are the portion of Dahua sample code:
// initialized play list
BOOL bOpenRet = PLAY_OpenStream(g_lRealPort, 0, 0, 1024 * 500);
if (bOpenRet)
{
// start play
BOOL bPlayRet = PLAY_Play(g_lRealPort, hMainWnd);
if (bPlayRet)
{
// monitor preview
long lRealHandle = CLIENT_RealPlayEx(lLoginHandle, nChannelID, 0);
if (0 != lRealHandle)
{
// set recall function handling data
CLIENT_SetRealDataCallBackEx(lRealHandle, RealDataCallBackEx, (DWORD)0, 0x1f);
}
else
{
//printf("Fail to play!\n");
PLAY_Stop(g_lRealPort);
PLAY_CloseStream(g_lRealPort);
}
}
else
{
PLAY_CloseStream(g_lRealPort);
}
}
The code above is connecting to cam using TCP and the streaming the video, the call back function RealDataCallBackEx is called for streaming, I can display the video on a Window, but how can I let OpenCV library to deal with it?
Here are the code of the RealDataCallBackEx function:
void __stdcall RealDataCallBackEx(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, LONG lParam, DWORD dwUser)
{
BOOL bInput = FALSE;
bInput = PLAY_InputData(g_lRealPort, pBuffer, dwBufSize);
}
If the IP camera uses certain standards you should be able to grab an image using the following OpenCV code (adapt where needed, i copied it from one of my own programs). I think you can also test this by pasting the url in your browser with the correct ip, port and login. I left the port at 88 because that is normally where you can send these commands to for an ip camera.
Mat returnFrame;
string url = "http://";
url.append("192.168.1.108");
url.append(":88/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=");
url.append("admin");
url.append("&pwd=");
url.append("admin");
VideoCapture cap(url);
if (cap.isOpened()) {
Mat frame;
if (cap.read(frame) == false) {
cout << "Unable to grab frame" << endl;
} else returnFrame = frame.clone();
cap.release();
} else cout << "Can't open URL" << endl;
if (returnFrame.empty()) cout << "No frame to grab for cam!" << endl;
else cout << "Cam Grabbed frame succesfully" << endl;
If you want to turn a byte buffer into a OpenCV Mat you can use the following code:
byte buf[] = new byte[100];
//fill buffer here
Mat m = new Mat(1, 100, CvType.CV_8UC1);
m.put(0, 0, buf);
Be sure to define the size and type correctly. In this example it is a 1 channel Mat of 1 x 100 pixels.
I only succeeded with the function CLIENT_SnapPictureEx
CLIENT_SetSnapRevCallBack(OnSnapRevMessage, dwUser);
NET_SNAP_PARAMS _netSnapParam;
_netSnapParam.Channel = (uint)ChannelNum;
_netSnapParam.mode = 1;
CLIENT_SnapPictureEx(lLoginID, _netSnapParam, reserved);
private void SnapRevCallBack(IntPtr lLoginID, IntPtr pBuf, uint RevLen, uint EncodeType, uint CmdSerial, IntPtr dwUser)
{
byte[] data = new byte[RevLen];
Marshal.Copy(pBuf, data, 0, (int)RevLen);
img = Cv2.ImDecode(data, ImreadModes.Color);
}

How do I get the DC coefficient from a jpg using the jpg library?

I am new to this stuff, but I need to get the dc-coefficient from a jpeg using the jpeg library?
I was told as a hint that the corresponding function is in jdhuff.c, but I can't find it. I tried to find a decent article about the jpg library where I can get this, but no success so far.
So I hope you guys can help me a bit and point me to either some documentation or have a hint.
So, here is what I know:
A jpg picture consists of 8x8 Blocks. That are 64 Pixels. 63 of it are named AC and 1 is named DC. Thats the coefficient. The position is at array[0][0].
But how do I exactly read that with the jpg library? I am using C++.
edit:
This is what I have so far:
read_jpeg::read_jpeg( const std::string& filename )
{
FILE* fp = NULL; // File-Pointer
jpeg_decompress_struct cinfo; // jpeg decompression parameters
JSAMPARRAY buffer; // Output row-buffer
int row_stride = 0; // physical row width
my_error_mgr jerr; // Custom Error Manager
// Set Error Manager
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
// Handle longjump
if (setjmp(jerr.setjmp_buffer)) {
// JPEG has signaled an error. Clean up and throw an exception.
jpeg_destroy_decompress(&cinfo);
fclose(fp);
throw std::runtime_error("Error: jpeg has reported an error.");
}
// Open the file
if ( (fp = fopen(filename.c_str(), "rb")) == NULL )
{
std::stringstream ss;
ss << "Error: Cannot read '" << filename.c_str() << "' from the specified location!";
throw std::runtime_error(ss.str());
}
// Initialize jpeg decompression
jpeg_create_decompress(&cinfo);
// Show jpeg where to read the data
jpeg_stdio_src(&cinfo, fp);
// Read the header
jpeg_read_header(&cinfo, TRUE);
// Decompress the file
jpeg_start_decompress(&cinfo);
// JSAMPLEs per row in output buffer
row_stride = cinfo.output_width * cinfo.output_components;
// Make a one-row-high sample array
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
// Read image using jpgs counter
while (cinfo.output_scanline < cinfo.output_height)
{
// Read the image
jpeg_read_scanlines(&cinfo, buffer, 1);
}
// Finish the decompress
jpeg_finish_decompress(&cinfo);
// Release memory
jpeg_destroy_decompress(&cinfo);
// Close the file
fclose(fp);
}
This is not possible using the standard API. With libjpeg API the closest you can get is raw pixel data of Y/Cb/Cr channels.
To get coefficients' data you'd need to hack the decode_mcu function (or its callers) to save the data decoded there.