YARP
Yet Another Robot Platform
MjpegStream.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 
6 #include "MjpegStream.h"
7 #include "MjpegDecompression.h"
8 #include "MjpegLogComponent.h"
9 
10 #include <yarp/sig/Image.h>
12 
13 #include <cstdio>
14 #include <cstring>
15 
16 using namespace yarp::os;
17 using namespace yarp::sig;
18 
20  if (remaining==0) {
21  if (phase==1) {
22  phase = 2;
23  cursor = (char*)(img.getRawImage());
24  remaining = img.getRawImageSize();
25  } else if (phase==3) {
26  phase = 4;
27  cursor = nullptr;
28  remaining = blobHeader.blobLen;
29  } else {
30  phase = 0;
31  }
32  }
33  while (phase==0 && delegate->getInputStream().isOk()) {
34  std::string s;
35  do {
36  s = delegate->getInputStream().readLine();
37  yCTrace(MJPEGCARRIER, "Read \"%s\"", s.c_str());
38  } while ((s.length()==0||s[0]!='-') && delegate->getInputStream().isOk());
39  s = delegate->getInputStream().readLine();
40  if (s!="Content-Type: image/jpeg") {
41  if (!delegate->getInputStream().isOk()) {
42  break;
43  }
44  yCWarning(MJPEGCARRIER, "Unknown content type - \"%s\"", s.c_str());
45  continue;
46  }
47  yCTrace(MJPEGCARRIER, "Read content type - \"%s\"", s.c_str());
48 
49  s = delegate->getInputStream().readLine();
50  yCTrace(MJPEGCARRIER, "Read content length - \"%s\"", s.c_str());
51  Bottle b(s);
52  if (b.get(0).asString()!="Content-Length:") {
53  if (!delegate->getInputStream().isOk()) {
54  break;
55  }
56  yCWarning(MJPEGCARRIER, "Expected Content-Length: got - \"%s\"", b.get(0).asString().c_str());
57  continue;
58  }
59  int len = b.get(1).asInt32();
60  yCTrace(MJPEGCARRIER, "Length is \"%d\"", len);
61  do {
62  s = delegate->getInputStream().readLine();
63  yCTrace(MJPEGCARRIER, "Read \"%s\"", s.c_str());
64  } while (s.length()>0);
65  if (autocompress) {
66  cimg.allocate(len);
67  delegate->getInputStream().readFull(cimg.bytes());
68  if (!decompression.decompress(cimg.bytes(), img)) {
69  if (delegate->getInputStream().isOk()) {
70  yCError(MJPEGCARRIER, "Skipping a problematic JPEG frame");
71  }
72  }
73  imgHeader.setFromImage(img);
74  phase = 1;
75  cursor = (char*)(&imgHeader);
76  remaining = sizeof(imgHeader);
77  } else {
78  // User wants us to pass on jpeg bytes, without compressing.
79  // This can save time if not every frame will be used.
80 
81  // We pass on the information in bottle-blob-compatible format.
82  phase = 3;
83  blobHeader.init(len);
84  cursor = (char*)(&blobHeader);
85  remaining = sizeof(blobHeader);
86  }
87  }
88 
89  if (remaining>0) {
90  int allow = remaining;
91  if ((int)b.length()<allow) {
92  allow = b.length();
93  }
94  if (cursor!=nullptr) {
95  memcpy(b.get(),cursor,allow);
96  cursor+=allow;
97  remaining-=allow;
98  yCTrace(MJPEGCARRIER, "returning %d bytes", allow);
99  return allow;
100  } else {
101  int result = delegate->getInputStream().read(b);
102  yCTrace(MJPEGCARRIER, "Read %d bytes", result);
103  if (result>0) {
104  remaining-=result;
105  yCTrace(MJPEGCARRIER, "%d bytes of meat", result);
106  return result;
107  }
108  }
109  }
110  return -1;
111 }
112 
113 
114 void MjpegStream::write(const Bytes& b) {
115  delegate->getOutputStream().write(b);
116 }
const yarp::os::LogComponent & MJPEGCARRIER()
void write(const yarp::os::Bytes &b) override
Write a block of bytes to the stream.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
A simple abstraction for a block of bytes.
Definition: Bytes.h:25
size_t length() const
Definition: Bytes.cpp:22
const char * get() const
Definition: Bytes.cpp:27
virtual int read()
Read and return a single byte.
Definition: InputStream.cpp:20
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCTrace(component,...)
Definition: LogComponent.h:85
#define yCWarning(component,...)
Definition: LogComponent.h:143
::ssize_t ssize_t
Definition: numeric.h:86
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:22