YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
ffmpegPortmonitor.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
15// Local imports
16#include "ffmpegPortmonitor.h"
17#include "constants.h"
18// YARP imports
20#include <yarp/os/Time.h>
21#include <yarp/sig/all.h>
22// Standard imports
23#include <cstring>
24#include <cmath>
25#include <algorithm>
26#include <iostream>
27#include <sstream>
28#include <mutex>
29#include <iomanip>
30
31// Ffmpeg imports
32extern "C" {
33 #include <libavcodec/avcodec.h>
34 #include <libavutil/opt.h>
35 #include <libavutil/imgutils.h>
36 #include <libavformat/avformat.h>
37 #include <libswscale/swscale.h>
38}
39
40using namespace yarp::os;
41using namespace yarp::sig;
42
43namespace {
44
45// YARP logging component
47 "yarp.carrier.portmonitor.image_compression_ffmpeg",
51 nullptr)
52}
53
62void split(const std::string &s, char delim, std::vector<std::string> &elements) {
63 std::istringstream iss(s);
64 std::string item;
65 while (std::getline(iss, item, delim)) {
66 elements.push_back(item);
67 }
68}
69
70// As per version 5.1.2 of ffmpeg, there seem to be race conditions between sws_scale and
71// sws_freeContext even when called from different instances on different threads.
72// We use a static mutex to prevent segmentation faults when connecting two port monitors
73// to the same sender or receiver.
74static std::mutex instances_mutex;
75
77{
78 // Check if this is sender or not
79 senderSide = (options.find("sender_side").asBool());
80 printStatistics = false;
86
87 // Parse command line parameters and set them into global variable "paramsMap"
88 std::string str = options.find("carrier").asString();
89 int frameRate = 15;
91 return false;
92 }
93
94 // Prepare codec context
95 if (codecContext == NULL) {
97 } else {
98 yCError(FFMPEGMONITOR, "Codec context is already allocated");
99 return false;
100 }
101 if (!codecContext) {
102 yCError(FFMPEGMONITOR, "Could not allocate video codec context");
103 return false;
104 }
105
106 if (!codec->pix_fmts)
107 {
108 yCWarning(FFMPEGMONITOR, "The specified codec (%s) has unknown available pixel formats. There might be visualization issues.", codec->name);
109 }
110 else
111 {
112 std::stringstream pixelFormatList;
113 bool found = false;
114 size_t i = 0;
115 AVPixelFormat test = codec->pix_fmts[i];
116
117 if (test == AV_PIX_FMT_NONE)
118 {
119 yCError(FFMPEGMONITOR, "The specified codec (%s) has no available pixel format.", codec->name);
120 return false;
121 }
122
123 pixelFormatList << test;
124 while (test != AV_PIX_FMT_NONE)
125 {
126 if (test == pixelFormat)
127 {
128 found = true;
129 break;
130 }
131 ++i;
132 test = codec->pix_fmts[i];
133
134 if (test != AV_PIX_FMT_NONE)
135 {
136 pixelFormatList << ", " << test;
137 }
138 }
139
140 if (!found)
141 {
143
145 {
146 yCError(FFMPEGMONITOR, "The specified codec (%s) is not compatible with the default pixel format AV_PIX_FMT_YUV420P (code %d). "
147 "Try specifying the suggested pixel format of the codec with the option \"pixel_format.%d\". "
148 "The available pixel formats are %s.",
150 }
151 else
152 {
153 yCError(FFMPEGMONITOR, "The specified codec (%s) is not compatible with the specified pixel format (code %d). "
154 "The available pixel formats are as follows %s (suggested = %d).",
155 codec->name, pixelFormat, pixelFormatList.str().c_str(), suggestedFormat);
156 }
157 return false;
158 }
159 }
160
161 firstTime = true;
162
163 // Set time base parameter
164 codecContext->time_base.num = 1;
165 codecContext->time_base.den = frameRate;
166 // Set command line params
167 if (setCommandLineParams() == -1) {
168 return false;
169 }
170
171 return true;
172}
173
175{
176 paramsMap.clear();
177
178 // Check if codec context is freeable, if yes free it.
179 if (codecContext != NULL) {
180#if LIBAVCODEC_VERSION_MAJOR < 61
181 // See https://github.com/FFmpeg/FFmpeg/blob/n7.0/libavcodec/avcodec.h#L2381-L2384
183#endif
186 }
187}
188
190{
191 yCTrace(FFMPEGMONITOR, "setparam");
192 return false;
193}
194
196{
197 yCTrace(FFMPEGMONITOR, "getparam");
198 return false;
199}
200
202{
203 if (senderSide) {
204 // If sender side
205 yCTrace(FFMPEGMONITOR, "accept - sender");
206 // Try to cast the Thing into an Image
207 Image* img = thing.cast_as< Image >();
208 // If cast fails, try to cast the Thing into a Bottle
209 if(img == nullptr) {
210 Bottle* bt = thing.cast_as<Bottle>();
211 // If cast fails, return error
212 if (bt == nullptr) {
213 yCError(FFMPEGMONITOR, "Expected type Image or Bottle in sender side, but got wrong data type!");
214 return false;
215 }
216 }
217 }
218 else {
219 // If receiver side
220 yCTrace(FFMPEGMONITOR, "accept - receiver");
221 // Try to cast the Thing into a Bottle
222 Bottle* bt = thing.cast_as<Bottle>();
223 // If cast fails, return error
224 if(bt == nullptr){
225 yCError(FFMPEGMONITOR, "Expected type Bottle in receiver side, but got wrong data type!");
226 return false;
227 }
228 }
229 return true;
230}
231
233{
234 double now = yarp::os::Time::now();
235 const double printInterval = 5.0;
236
237 if (statisticsCounter < 0)
238 {
239 previousFrameTime = now;
242 }
243 else
244 {
245 size_t outputData{0};
246 inputBottle.toBinary(&outputData);
247 double dt = now - previousFrameTime;
248 double bandwidth = outputData * 8 / dt /1000;
253
254 }
256 {
259 std::stringstream bandwidthString, lagString;
260 bandwidthString << std::fixed << std::setprecision(2) << bandwidthRunningAverage;
261 lagString << std::fixed << std::setprecision(3) << lagRunningAverage * 1000;
262 yCInfo(FFMPEGMONITOR, "Statistics: current bandwidth %s kb/s, codec computational time %s ms",
263 bandwidthString.str().c_str(), lagString.str().c_str());
264 }
265}
266
268{
269 double startTime = yarp::os::Time::now();
270 if (senderSide) {
271 bool success = true;
272 yCTrace(FFMPEGMONITOR, "update - sender");
273 // Cast Thing into an Image
274 Image* img = thing.cast_as< Image >();
275
276 if (img == nullptr) {
277 Bottle* bot = thing.cast_as<Bottle>();
279 {
280 yCError(FFMPEGMONITOR, "The input type is a Bottle, but it cannot be copied to an Image");
281 success = false;
282 }
283 img = &imageBottleBuffer;
284 }
285
286 // Allocate memory for packet
287 AVPacket *packet = av_packet_alloc();
288 if (packet == NULL) {
289 yCError(FFMPEGMONITOR, "Error in packet allocation");
290 success = false;
291 }
292
293 // Call compress function
294 if (success && compress(img, packet) != 0) {
295 yCError(FFMPEGMONITOR, "Error in compression");
296 success = false;
297 }
298
299 // Insert compressed image into a Bottle to be sent
300 data.clear();
301
302 int successCode = success ? 1 : 0;
304 data.addInt32(img->width());
305 data.addInt32(img->height());
306 data.addInt32(img->getPixelCode());
307 data.addInt32(img->getPixelSize());
308
309 if (success) { // If compression was successful, insert also compressed data
310 // Packet
311 Value p(packet, sizeof(*packet));
312 data.add(p);
313 // Packet data
314 Value d(packet->data, packet->size);
315 data.add(d);
316 // Buffer size
317 data.addInt32(packet->buf->size);
318 // Buffer data
319 Value bd(packet->buf->data, packet->buf->size);
320 data.add(bd);
321
322 // Side data elements
323 for (int i = 0; i < packet->side_data_elems; i++) {
324 data.addInt32(packet->side_data[i].size);
325 data.addInt32(packet->side_data[i].type);
326 Value sd(packet->side_data[i].data, packet->side_data[i].size);
327 data.add(sd);
328 }
329 }
330
331 if (printStatistics)
332 {
334 }
335
337 // Free the memory allocated for the packet
338 av_packet_unref(packet);
339 }
340 else {
341
342 yCTrace(FFMPEGMONITOR, "update - receiver");
343 // Cast the Thin as a Bottle
345 // Fill the final image with zeros
346 imageOut.zero();
347 // Extract decompression data from the Bottle
348 int width = compressedBottle->get(1).asInt32();
349 int height = compressedBottle->get(2).asInt32();
350 int pixelCode = compressedBottle->get(3).asInt32();
351 int pixelSize = compressedBottle->get(4).asInt32();
352 // Set information into final image
353
355 {
358 imageOut.resize(width, height);
359 }
360 else
361 {
362 yCError(FFMPEGMONITOR, "Invalid input pixel code");
363 }
364
365 // Check if compression was successful
366 if (compressedBottle->get(0).asInt32() == 1) {
367 bool success = true;
368 // Get compressed image from Bottle
369 AVPacket* tmp = (AVPacket*) compressedBottle->get(5).asBlob();
370 // Allocate memory for packet
371 AVPacket* packet = av_packet_alloc();
372 // Set all packet parameters
373 packet->dts = tmp->dts;
374 packet->duration = tmp->duration;
375 packet->flags = tmp->flags;
376 packet->pos = tmp->pos;
377 packet->pts = tmp->pts;
378 packet->side_data_elems = 0;
379 packet->stream_index = tmp->stream_index;
380 packet->size = tmp->size;
381 // Image data
382 packet->data = (uint8_t *) compressedBottle->get(6).asBlob();
383 // Buffer data
384 packet->buf = av_buffer_create((uint8_t *) compressedBottle->get(8).asBlob(),
385 compressedBottle->get(7).asInt32(), av_buffer_default_free,
386 nullptr, AV_BUFFER_FLAG_READONLY);
387
388 // Packet side data
389 for (int i = 0; i < tmp->side_data_elems; i++) {
390
391 int ret = av_packet_add_side_data(packet,
392 (AVPacketSideDataType) compressedBottle->get(10).asInt32(), // Type
393 (uint8_t *) compressedBottle->get(11).asBlob(), // Data
394 compressedBottle->get(9).asInt32()); // Size
395 if (ret < 0) {
396 success = false;
397 break;
398 }
399 }
400
401 // Call to decompress function
402 if (success && decompress(packet, width, height, pixelCode) != 0) {
403 yCError(FFMPEGMONITOR, "Error in decompression");
404 }
405
406 if (printStatistics)
407 {
409 }
410
411 // Free memory allocated for side data and packet
412 av_freep(&packet->side_data);
413 av_freep(&packet);
414
415 }
416
418
419 }
420 return th;
421}
422
424
425 yCTrace(FFMPEGMONITOR, "compress");
428
429 // Get width and height
430 int w = img->width();
431 int h = img->height();
432
433 // Allocate video frame for original frames
435 if (startFrame == NULL) {
436 yCError(FFMPEGMONITOR, "Cannot allocate starting frame!");
437 return -1;
438 }
439
440 // Allocate a video frame for end frame
442 if (endFrame == NULL) {
443 yCError(FFMPEGMONITOR, "Cannot allocate end frame!");
445 return -1;
446 }
447
448 // Allocate space into start frame to contain data
449 int success = av_image_alloc(startFrame->data, startFrame->linesize,
450 w, h,
452
453 if (success < 0) {
454 yCError(FFMPEGMONITOR, "Cannot allocate starting frame buffer!");
457 return -1;
458 }
459
460 // Set Image data into AVFrame
461 startFrame->linesize[0] = img->getRowSize();
462 // Free old pointer (because we will use the buffer contained into img)
463 av_freep(&startFrame->data[0]);
464 startFrame->data[0] = img->getRawImage();
465 startFrame->height = h;
466 startFrame->width = w;
468
469 // Allocate memory for end frame data
470 success = av_image_alloc(endFrame->data, endFrame->linesize,
471 w, h, pixelFormat, 16);
472
473 if (success < 0) {
474 yCError(FFMPEGMONITOR, "Cannot allocate end frame buffer!");
477 return -1;
478 }
479
480 // Set end frame parameters
481 endFrame->height = h;
482 endFrame->width = w;
483 endFrame->format = pixelFormat;
484
485 {
486 std::lock_guard<std::mutex> lock(instances_mutex);
487
488 // Convert the image from start format into end format
489 static struct SwsContext *img_convert_ctx;
490
491 // Allocate context for conversion
494 w, h,
497 NULL, NULL, NULL);
498 if (img_convert_ctx == NULL) {
499 yCError(FFMPEGMONITOR, "Cannot initialize pixel format conversion context!");
500 av_freep(&endFrame->data[0]);
503 return -1;
504 }
505
506 // Perform conversion
507 int ret = sws_scale(img_convert_ctx, startFrame->data, startFrame->linesize, 0,
508 h, endFrame->data, endFrame->linesize);
509
510 if (ret < 0) {
511 yCError(FFMPEGMONITOR, "Could not convert pixel format!");
513 av_freep(&endFrame->data[0]);
516 return -1;
517 }
518
519 if (firstTime) {
520 // If this is the first compression
521
522 // Set codec context parameters
523 codecContext->width = w;
524 codecContext->height = h;
525 codecContext->pix_fmt = pixelFormat;
526
527 // Open codec
529 if (ret < 0) {
530 yCError(FFMPEGMONITOR, "Could not open codec");
532 av_freep(&endFrame->data[0]);
535 return -1;
536 }
537 firstTime = false;
538 }
539
540 // Set presentation timestamp
541#if LIBAVCODEC_VERSION_MAJOR >= 61
542 // See https://github.com/FFmpeg/FFmpeg/commit/6b6f7db81932f94876ff4bcfd2da0582b8ab897e
543 endFrame->pts = codecContext->frame_num;
544#else
545 endFrame->pts = codecContext->frame_number;
546#endif
547
548 // Send image frame to codec
550 if (ret < 0) {
551 yCError(FFMPEGMONITOR, "Error sending a frame for encoding");
553 av_freep(&endFrame->data[0]);
556 return -1;
557 }
558
559 // Receive compressed data into packet
562 av_freep(&endFrame->data[0]);
565
566
567 if (ret == AVERROR(EAGAIN)) {
568 // Not enough data
569 yCError(FFMPEGMONITOR, "Error EAGAIN");
570 return -1;
571 } else if (ret == AVERROR_EOF) {
572 // End of file reached
573 yCError(FFMPEGMONITOR, "Error EOF");
574 return -1;
575 } else if (ret < 0) {
576 yCError(FFMPEGMONITOR, "Error during encoding");
577 return -1;
578 }
579 }
580
581 return 0;
582}
583
585
586 yCTrace(FFMPEGMONITOR, "decompress");
589
590 if (firstTime) {
591 // If this is the first decompression
592
593 // Set codec context parameters
594 codecContext->width = w;
595 codecContext->height = h;
596 codecContext->pix_fmt = pixelFormat;
597
598 // Open codec
600 if (ret < 0) {
601 yCError(FFMPEGMONITOR, "Could not open codec");
602 return -1;
603 }
604 firstTime = false;
605 }
606
607 // Allocate video frame
609 if (startFrame == NULL) {
610 yCError(FFMPEGMONITOR, "Could not allocate start frame!");
611 return -1;
612 }
613
614 // Send compressed packet to codec
616 if (ret < 0) {
617 yCError(FFMPEGMONITOR, "Error sending a frame for decoding");
619 return -1;
620 }
621
622 // Receive decompressed image into an AVFrame
624 if (ret == AVERROR(EAGAIN)) {
625 // No enough data
626 yCError(FFMPEGMONITOR, "Error EAGAIN");
628 return -1;
629 }
630 else if (ret == AVERROR_EOF) {
631 // End of file reached
632 yCError(FFMPEGMONITOR, "Error EOF");
634 return -1;
635 }
636 else if (ret < 0) {
637 yCError(FFMPEGMONITOR, "Error during decoding");
639 return -1;
640 }
641
642 // Allocate a video frame for end frame
644 if (endFrame == NULL) {
645 yCError(FFMPEGMONITOR, "Could not allocate start frame!");
647 return -1;
648 }
649
650 // Allocate memory into end frame to contain data
651 int success = av_image_alloc(endFrame->data, endFrame->linesize,
652 w, h,
654
655 if (success < 0) {
656 yCError(FFMPEGMONITOR, "Error allocating end frame buffer!");
659 return -1;
660 }
661
662 // Set end frame parameters
663 endFrame->height = h;
664 endFrame->width = w;
666
667 {
668 std::lock_guard<std::mutex> lock(instances_mutex);
669
670 // Convert the image into RGB format
671 static struct SwsContext *img_convert_ctx;
672
673 // Allocate conversion context
676 w, h,
679 NULL, NULL, NULL);
680 if (img_convert_ctx == NULL) {
681 yCError(FFMPEGMONITOR, "Cannot initialize the pixel format conversion context!");
682 av_freep(&endFrame->data[0]);
685 return -1;
686 }
687
688 // Perform conversion
689 ret = sws_scale(img_convert_ctx, startFrame->data, startFrame->linesize, 0,
690 h, endFrame->data, endFrame->linesize);
691
692 if (ret < 0) {
693 yCError(FFMPEGMONITOR, "Could not convert pixel format!");
694 av_freep(&endFrame->data[0]);
698 return -1;
699 }
700
701 // Copy decompressed data from end frame to imageOut
702 memcpy(imageOut.getRawImage(), endFrame->data[0], success);
703
704 // Free allocated memory
705 av_freep(&endFrame->data[0]);
709 }
710
711 return 0;
712
713}
714
716
717 std::vector<std::string> parameters;
718 // Split command line string using '+' delimiter
719 split(carrierString, '+', parameters);
720
721 bool standardCodec = false;
722 bool customEnc = false;
723 bool customDec = false;
724
725 // Iterate over result strings
726 for (std::string& param: parameters) {
727
728 // Skip YARP initial parameters
730 continue;
731 }
732
733 // If there is no '.', the param is bad formatted, return error
734 auto pointPosition = param.find('.');
735 if (pointPosition == std::string::npos) {
736 yCError(FFMPEGMONITOR, "Error while parsing parameter %s. Missing '.'!", param.c_str());
737 return false;
738 }
739
740 // Otherwise, separate key and value
741 std::string paramKey = param.substr(0, pointPosition);
742 std::string paramValue = param.substr(pointPosition + 1, param.length());
743
744 // Parsing codec
746
747 if (customEnc || customDec)
748 {
749 yCError(FFMPEGMONITOR, "Cannot set both %s and %s/%s together.",
753 codecOut = nullptr;
754 return false;
755 }
756
757 bool found = false;
758 // Iterate over codecs command line possibilities
759 for (size_t i = 0; i < FFMPEGPORTMONITOR_CL_CODECS.size(); i++) {
760 // If found
762 // Set codec id basing on codec command line name
764 // Find encoder/decoder
765 if (senderSide) {
767 } else {
769 }
770
771 if (!codecOut) {
772 yCError(FFMPEGMONITOR, "Can't find codec %s", paramValue.c_str());
773 codecOut = nullptr;
774 return false;
775 }
776
777 standardCodec = true;
778 found = true;
779 break;
780 }
781 }
782
783 // If not found, unrecognized codec, return error
784 if (!found) {
785 yCError(FFMPEGMONITOR, "Unrecognized codec: %s", paramValue.c_str());
786 return false;
787 }
788
789 continue; //avoid to add this parameter to paramsMap
790 }
792 {
793 if (!senderSide)
794 {
795 customEnc = true;
796 continue; //The custom encoder need to be set on the sender side only. Later we check that the custom decoder has been set too.
797 }
798
799 if (standardCodec)
800 {
801 yCError(FFMPEGMONITOR, "Cannot set both %s and %s/%s together.",
805 codecOut = nullptr;
806 return false;
807 }
808
809
811
812 if (!codecOut) {
813 yCError(FFMPEGMONITOR, "Can't find encoder %s", paramValue.c_str());
814 codecOut = nullptr;
815 return false;
816 }
817
818 customEnc = true;
819 continue; //avoid to add this parameter to paramsMap
820 }
822 {
823 if (senderSide)
824 {
825 customDec = true;
826 continue; //The custom decoder need to be set on the receiver side only. Later we check that the custom encoder has been set too.
827 }
828
829 if (standardCodec)
830 {
831 yCError(FFMPEGMONITOR, "Cannot set both %s and %s/%s together.",
835 codecOut = nullptr;
836 return false;
837 }
838
840
841 if (!codecOut) {
842 yCError(FFMPEGMONITOR, "Can't find decoder %s", paramValue.c_str());
843 codecOut = nullptr;
844 return false;
845 }
846
847 customDec = true;
848 continue; //avoid to add this parameter to paramsMap
849 }
851 {
852 pixelFormatOut = static_cast<AVPixelFormat>(std::atoi(paramValue.c_str()));
853 continue; //avoid to add this parameter to paramsMap
854 }
856 {
857 frameRate = std::atoi(paramValue.c_str());
858 continue; //avoid to add this parameter to paramsMap
859 }
861 {
862 printStatistics = std::atoi(paramValue.c_str());
863 continue; //avoid to add this parameter to paramsMap
864 }
865
866 // Save param into params map
867 paramsMap.insert( std::pair<std::string, std::string>(paramKey, paramValue) );
868 }
869
870 if (!standardCodec && !customEnc && !customDec)
871 {
872 // Set default codec
874 if (senderSide) {
876 } else {
878 }
879
880 if (!codecOut) {
881 yCError(FFMPEGMONITOR, "Can't find default codec (mpeg2video).");
882 return false;
883 }
884 }
885
886 if (customEnc && !customDec)
887 {
888 yCError(FFMPEGMONITOR, "A custom encoder has been specified, but not a custom decoder.");
889 return false;
890 }
891
892 if (!customEnc && customDec)
893 {
894 yCError(FFMPEGMONITOR, "A custom decoder has been specified, but not a custom encoder.");
895 return false;
896 }
897
898 return true;
899
900}
901
903
904 // Iterate over all saved parameters
905 for (auto const& x : paramsMap) {
906
907 // Get key and value
908 std::string key = x.first;
909 std::string value = x.second;
910
911 // Try to set this pair (key, value) into codec context (global parameters).
912 int globalError = av_opt_set(codecContext, key.c_str(), value.c_str(), 0);
913 // Try to set this pair (key, value) into codec context -> priv data (parameters that are specific for a codec).
914 int privError = av_opt_set(codecContext->priv_data, key.c_str(), value.c_str(), 0);
915
916 // If the param exists, but the value is out of range
918 yCError(FFMPEGMONITOR, "Parameter out of range: %s", key.c_str());
919 return -1;
920 }
921 // If the param exists, but the value is invalid
922 else if (globalError == AVERROR(EINVAL) || privError == AVERROR(EINVAL)) {
923 yCError(FFMPEGMONITOR, "Invalid value for parameter: %s", key.c_str());
924 return -1;
925 }
926 // If the param doesn't exists (we check only in sender side because some parameters doesn't exist in the decoders)
928 yCError(FFMPEGMONITOR, "Parameter not found: %s", key.c_str());
929 return -1;
930 }
931
932 }
933 return 0;
934}
void split(const std::string &s, char delim, std::vector< std::string > &elements)
@ VOCAB_PIXEL_INVALID
Definition Image.h:41
bool ret
void updateStatistics(yarp::os::Bottle &inputBottle, double currentLag)
Print some network statistics.
yarp::sig::FlexImage imageOut
The final decompressed image that will be sent to the original destination.
int statisticsCounter
Utility counter for printing statistics.
int compress(yarp::sig::Image *img, AVPacket *pkt)
This function performs all the compression actions on the incoming Image and saves the resulting comp...
AVPixelFormat pixelFormat
Ffmpeg pixel format.
bool getParamsFromCommandLine(std::string carrierString, const AVCodec *&codecOut, AVPixelFormat &pixelFormatOut, int &frameRate)
This function parses the command line parameters from a string containing the entire command used to ...
bool accept(yarp::os::Things &thing) override
This function is used by the port monitor to decide if an incoming packet can be accepted (it tries t...
int setCommandLineParams()
This function iterates over the attribute paramsMap and sets all the specified parameters into the at...
bool firstTime
Boolean variable used to check if the current call to the "compression" (or "decompression") function...
yarp::sig::Image imageBottleBuffer
The final decompressed image that will be sent to the original destination.
yarp::os::Things & update(yarp::os::Things &thing) override
This function is the one that manipulates the incoming packet.
yarp::os::Bottle data
The bottle that is filled with compressed image and all the information needed for decompression (it ...
const AVCodec * codec
Ffmpeg structure containing all codec information needed for compression / decompression.
double lagRunningAverage
Variable storing the current lag for statistics.
double previousFrameTime
Seconds since epoch of the previous frame;.
yarp::os::Things th
The object returned by the "update" function; it can be a yarp::os::Bottle (sender side) or a yarp::s...
bool printStatistics
Boolean variable used to check whether the bandwidth statistics should be printed.
bool senderSide
Boolean variable that tells if the current execution is in sender side or not.
bool create(const yarp::os::Property &options) override
This function is called when the object is created and it is used to initialize all its attributes.
bool setparam(const yarp::os::Property &params) override
This will be called when the portmonitor carrier parameters are set via YARP admin port.
bool getparam(yarp::os::Property &params) override
This will be called when the portmonitor carrier parameters are requested via YARP admin port.
int decompress(AVPacket *pkt, int w, int h, int pixelCode)
This function decompresses the incoming AVPacket passed as parameter and saves decompressed data into...
double previousStatisticPrintTime
Utility variable to store the time in which the last time the statistics have been printed.
std::map< std::string, std::string > paramsMap
Structure that maps every parameter inserted from command line into its value (both as strings).
void destroy(void) override
This function is called when the execution is terminated and the object is destroyed.
AVCodecContext * codecContext
Ffmpeg structure containing all codec context information needed for compression / decompression.
double bandwidthRunningAverage
Variable storing the current bandwidth average for statistics.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
void add(const Value &value)
Add a Value to the bottle, at the end of the list.
Definition Bottle.cpp:309
void clear()
Empties the bottle of any objects it contains.
Definition Bottle.cpp:121
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition Bottle.cpp:140
A mini-server for performing network communication in the background.
static LogCallback printCallback()
Get current print callback.
Definition Log.cpp:873
static LogType minimumPrintLevel()
Get current minimum print level.
Definition Log.cpp:833
@ LogTypeReserved
Definition Log.h:98
static bool copyPortable(const PortWriter &writer, PortReader &reader)
Copy one portable to another, via writing and reading.
Definition Portable.cpp:16
A class for storing options and configuration information.
Definition Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Base class for generic things.
Definition Things.h:18
T * cast_as()
Definition Things.h:53
void setPortWriter(yarp::os::PortWriter *writer)
Set the reference to a PortWriter object.
Definition Things.cpp:26
A single value (typically within a Bottle).
Definition Value.h:43
virtual bool asBool() const
Get boolean value.
Definition Value.cpp:186
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
void setPixelCode(int imgPixelCode)
Definition Image.h:366
void setPixelSize(size_t imgPixelSize)
Definition Image.h:371
Base class for storing images.
Definition Image.h:79
size_t width() const
Gets width of image in pixels.
Definition Image.h:171
size_t getRowSize() const
Size of the underlying image buffer rows.
Definition Image.h:197
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition Image.cpp:479
virtual size_t getPixelSize() const
Gets pixel size in memory in bytes.
Definition Image.cpp:385
void resize(size_t imgWidth, size_t imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Definition Image.cpp:402
void zero()
Set all pixels to 0.
Definition Image.cpp:395
size_t height() const
Gets height of image in pixels.
Definition Image.h:177
virtual int getPixelCode() const
Gets pixel type identifier.
Definition Image.cpp:390
File containing constans used in FfmpegPortmonitor.cpp.
static const std::vector< std::string > FFMPEGPORTMONITOR_IGNORE_PARAMS
This vector contains all parameters that have to be ignored while parsing command line string.
Definition constants.h:34
static const std::string FFMPEGPORTMONITOR_CL_CODEC_KEY
This string is the "key" value for the codec parameter.
Definition constants.h:48
static const std::string FFMPEGPORTMONITOR_CL_CUSTOM_DEC_KEY
This string is the "key" value for the custom decoder parameter.
Definition constants.h:70
static const std::vector< std::string > FFMPEGPORTMONITOR_CL_CODECS
This vector contains the only accepted values for the command line parameter "codec".
Definition constants.h:54
static std::map< int, int > FFMPEGPORTMONITOR_PIXELMAP
This structure maps YARP pixel format codec into Ffmpeg pixel format codes.
Definition constants.h:104
static const std::string FFMPEGPORTMONITOR_CL_PIXEL_FORMAT_KEY
This string is the "key" value for the pixel format parameter.
Definition constants.h:76
static const std::string FFMPEGPORTMONITOR_CL_CUSTOM_ENC_KEY
This string is the "key" value for the custom encoder parameter.
Definition constants.h:64
static const std::vector< int > FFMPEGPORTMONITOR_CODE_CODECS
This vector contains the codec ids corresponding to the codecs of the FFMPEGPORTMONITOR_CL_CODECS vec...
Definition constants.h:94
static const std::string FFMPEGPORTMONITOR_CL_FRAME_RATE_KEY
This string is the "key" value for the frame rate parameter.
Definition constants.h:82
static const std::string FFMPEGPORTMONITOR_CL_PRINT_STATISTICS_KEY
This string is the "key" value to enable the print statistics.
Definition constants.h:88
static AVPixelFormat FFMPEGPORTMONITOR_DEFAULT_PIXEL_FORMAT
Default pixel format to be used within ffmpeg.
Definition constants.h:116
static std::mutex instances_mutex
void split(const std::string &s, char delim, std::vector< std::string > &elements)
This function simply splits a string into a vector of strings basing on a delimiter character.
Header file of FfmpegPortmonitor: a port monitor for video compression/decompression.
#define yCInfo(component,...)
#define yCError(component,...)
#define yCTrace(component,...)
#define yCWarning(component,...)
#define YARP_LOG_COMPONENT(name,...)
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.