Transfer images on websocket by using boost library - c++

I want to transfer image data on websocket by using boost library.
How should I resolve below error?
At first, I confirmed to be able to transfer and receive text data by referring following URL.
https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/quick_start.html
And next, although I tried to transfer image, I got following error message.
websocket_client.cpp:563:38: error: no matching function for call to 'buffer(cv::Mat&)'
ws.write(boost::asio::buffer(img));
What I did are below.
read image file as 'img' by using opencv.
Change the code for transfer data
// Send the message
// ws.write(boost::asio::buffer(std::string(text)));
ws.write(boost::asio::buffer(img));

cv::Mat is not a buffer type or adaptable as such. If you have POD data, then you can "cast" it like the commenter says:
// don't do this:
buffer(&img, sizeof(img));
However, that's not safe:
static_assert(std::is_standard_layout_v<cv::Mat>);
static_assert(std::is_trivial_v<cv::Mat>);
The type is actually not bitwise copyable. But since there's a matrix, there is likely a contiguous region of data that is:
ws.write(net::buffer(img.data, img.total() * img.elemSize()));
This uses total() and elemSize(), links to the documentation.
Now, this will be enough if the receiving end already knows the dimensions. If not, send them first, e.g.:
uint32_t dimensions[] { htonl(image_witdh), htonl(image_height) };
std::vector<net::const_buffer> buffers {
net::buffer(dimensions),
net::buffer(img.data, img.total() * img.elemSize())
};
ws.write(buffers);

Related

I called av_probe_input_format3(), now I want to call avcodec_find_decoder(), how do I convert the format in a codec?

So... I'm dealing with a system that has input data coming in buffers (i.e. NOT a file). I want to determine which decoder to create to decompress an audio stream (MP3, WAV, OGG, ...) So obviously I do not know the input format.
I found out that I could determine the format using the av_probe_input_format[23]() functions. That part works great, I get a format pointer that matches the files that I use as input.
AVInputFormat * format(av_probe_input_format3(&pd, true, &score));
I can print the format->name and format->long_name and these are the correct type (so the detection is working as expected).
Now, I'm trying to understand how to convert that AVInputFormat * into a AVCodec * so I can call avcodec_alloc_context3(codec) to create the actual audio decoder.
I found a couple of functions, which I used like so:
AVCodecID const codec_id(av_codec_get_id(format->codec_tag, format->raw_codec_id));
AVCodec * codec(avcodec_find_decoder(codec_id));
Problem 1. the raw_codec_id field is marked as "private" (should not access/use anywhere in your client's code).
Problem 2. the first function always returns AV_CODEC_ID_NONE (0) so of course the second call fails each time.
Am I doing something wrong? Is there is way to instead create a generic decode that will automatically detect the type of audio I have as input? (that is, would that be the only way to make that work?)
Okay, so the fact is that trying to use these functions directly is pretty much futile. The problem I have with the design is that it forces me to actually have a callback and that callback forces me to have a thread (i.e. I have to somehow feed data from a stream, not a file or such!)
So I can use the avformat_open_input() as mentioned by Gyan, only I have to have my own AVIOContext. I was hoping I could just call functions with my incoming data and avoid the pipeline concept. The issue here is some background processes could be servers that use fork() and thus you need to be really careful (i.e. fork() is not friendly with threads).

Cannot Send Image File (image/jpg) Using Winsock WSABUF

I'm stuck and I need help.
I'm trying to write the correct code for sending back an image file so the web browser can render it. It can send back text/html just fine, but image/* is not working.
You can see the code and the URL is shown below.
https://github.com/MagnusTiberius/iocphttpd/blob/master/iocphttpl/SocketCompletionPortServer.cpp
What the browser is receiving is just a few bytes of image data.
I tried vector, std::string and const char* to set the values of WSABUF, but still the same few bytes are sent over.
Please let know what is the missing piece to make this one work.
Thanks in advance.
Here's your problem:
PerIoData->LPBuffer = _strdup(str.c_str());
The _strdup function only copies up until the first null, so it cannot be used to copy binary data. Consider using malloc and memcpy if you don't want to use the C++ library.
The alternate implementation (in the false branch) is also incorrect, because it saves the data in an object (vc) that goes out of scope before the I/O is completed. You could instead do something like
vector<char> * vc = new vector<char>;

Writing ITK (insight Toolkit) results to local buffer

After applying an ITK filter pipeline, how do I write back the result to a buffer to be used (outside ITK)?
The Insight Software Guide has an example Book 1: Chapter 4.1.7: "Importing Image Data from a Buffer", and the same example is also found in the WikiExamples.
It shows how one can wrap a ITK pointer around a C++ array to use it further by using the ImportImageFilter object.
However, this example then uses a Writer object to write the filtered result to a file.
How do I write the filtered result into another C++ array instead? Or how do I overwrite the array I've used as input?
In essence, I've an application which contains an image in a buffer (localBuffer) which I can wrap following the example code:
[...]
const bool filterOwnsBuffer= false;
importFilter->SetImportPointer( localBuffer, size[0]*size[1], filterOwnsBuffer );
I can then use it it in any itk pipeline and 'update' it at a certain stage:
[...]
FilterType::Pointer filter = FilterType::New();
filter->SetInput( importFilter->GetOutput() );
filter->Update();
How do I now ensure that localbuffer has the filtered values? Or, alternatively, how do I set a different resultbuffer to the output values? Do I have to use the image iterator and 'loop' over my buffer manually? Or can I use the filter->GetOutput() more directly?
A little code example or a link to an according example would be very much appreciated.
(Simply the "Exporting Image Data to a Buffer" equivalent to the given import example.)
ImageType::Pointer output = filter->GetOutput();
ImageType::PixelContainer * outputContainer = output->GetPixelContainer();
ImageType::PixelContainer::Element * resultBuffer = outputContainer->GetBufferPointer();
See the Image documentation and ImportImageContainer documentation.
Here is the remedy for me:
memcpy( buffer, filter->GetOutput()->GetBufferPointer(),
size[0]*size[1]*sizeof(InputPixelType));
This works because by the time the filter is destroyed the buffer was already parsed to "buffer", which is the pointer to your data.

What is the best way to return an image or video file from a function using c++?

I am writing a c++ library that fetches and returns either image data or video data from a cloud server using libcurl. I've started writing some test code but still stuck at designing API because I'm not sure about what's best way to handle these media files. Storing it in a char/string variable as binary data seems to work, but I wonder if that would take up too much RAM memory if the files are too big. I'm new to this, so please suggest a solution.
You can use something like zlib to compress it in memory, and then uncompress it only when it needs to be used; however, most modern computers have quite a lot of memory, so you can handle quite a lot of images before you need to start compressing. With videos, which are effectively a LOT of images, it becomes a bit more important -- you tend to decompress as you go, and possibly even stream-from-disk as you go.
The usual way to handle this, from an API point of view, is to have something like an Image object and a Video object (classes). These objects would have functions to "get" the uncompressed image/frame. The "get" function would check to see if the data is currently compressed; if it is, it would decompress it before returning it; if it's not compressed, it can return it immediately. The way the data is actually stored (compressed/uncompressed/on disk/in memory) and the details of how to work with it are thus hidden behind the "get" function. Most importantly, this model lets you change your mind later, adding additional types of compression, adding disk-streaming support, etc., without changing how the code that calls the get() function is written.
The other challenge is how you return an Image or Video object from a function. You can do it like this:
Image getImageFromURL( const std::string &url );
But this has the interesting problem that the image is "copied" during the return process (sometimes; depends how the compiler optimizes things). This way is more memory efficient:
void getImageFromURL( const std::string &url, Image &result );
This way, you pass in the image object into which you want your image loaded. No copies are made. You can also change the 'void' return value into some kind of error/status code, if you aren't using exceptions.
If you're worried about what to do, code for both returning the data in an array and for writing the data in a file ... and pass the responsability to choose to the caller. Make your function something like
/* one of dst and outfile should be NULL */
/* if dst is not NULL, dstlen specifies the size of the array */
/* if outfile is not NULL, data is written to that file */
/* the return value indicates success (0) or reason for failure */
int getdata(unsigned char *dst, size_t dstlen,
const char *outfile,
const char *resource);

sending a serialized type over a boost-asio socket connection using boost serialization

I am trying to send 1kb of data from a "server" to a "client", but I just can't get it right.
There are a few things that I NEED to do in this:
1) Need to use boost-asio sockets to transfer the data
2) Need to serialize a type I created (Packet) that will contain the data as a string or char*
Here is what is going on:
First, I get 1kb of data from a sample text file on the server. I get this and put it into the Packet type that I created. I have defined the data field in Packet to hold this data as a std::string. (I tried char* but it didnt work well - see next paragraph).
Second I serialize it using boost text_oarchive . I have no problems serializing the Packet type if it just contains a string, but what I really want is a way to serialize it with the data type being a char array (so that it works better with the socket below)
Third, I send it over a boost asio socket. Here I have a problem because I can't find a way to send a std::string over the socket connection. Everything I see as examples and in the documentation need a buffer using some type of char* and not a string.
its just a headache. can you help?
Everything I see as examples and in the documentation need a buffer
using some type of char* and not a string
That is correct, though it's quite simple to do using Boost.Serialization and Boost.Asio. You can serialize using a text_oarchive to a boost::asio::streambuf then send the resulting stream buffer contents using a socket.
See this question and my answer to that question for a more complete example.