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