Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit e459cdf

Browse files
committed
Finished the amlogic grabber for the 'WeTek Play'
1 parent b56a726 commit e459cdf

File tree

11 files changed

+265
-71
lines changed

11 files changed

+265
-71
lines changed

HyperionConfig.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
// Define to enable the framebuffer grabber
2222
#cmakedefine ENABLE_FB
2323

24+
// Define to enable the amlogic grabber
25+
#cmakedefine ENABLE_AMLOGIC
26+
2427
// Define to enable the osx grabber
2528
#cmakedefine ENABLE_OSX
2629

include/grabber/AmlogicWrapper.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
// Utils includes
88
#include <utils/Image.h>
9+
#include <utils/ColorBgr.h>
910
#include <utils/ColorRgb.h>
10-
#include <utils/ColorRgba.h>
1111
#include <utils/GrabbingMode.h>
1212
#include <utils/VideoMode.h>
1313

@@ -80,7 +80,7 @@ public slots:
8080
QTimer _timer;
8181

8282
/// The image used for grabbing frames
83-
Image<ColorRgb> _image;
83+
Image<ColorBgr> _image;
8484
/// The actual grabber
8585
AmlogicGrabber * _frameGrabber;
8686
/// The processor for transforming images to led colors

include/utils/ColorBgr.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
3+
// STL includes
4+
#include <cstdint>
5+
#include <iostream>
6+
7+
struct ColorBgr;
8+
9+
///
10+
/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the
11+
/// structure is exactly 3-bytes for easy writing to led-device
12+
///
13+
struct ColorBgr
14+
{
15+
/// The blue color channel
16+
uint8_t blue;
17+
/// The green color channel
18+
uint8_t green;
19+
/// The red color channel
20+
uint8_t red;
21+
22+
/// 'Black' RgbColor (0, 0, 0)
23+
static ColorBgr BLACK;
24+
/// 'Red' RgbColor (255, 0, 0)
25+
static ColorBgr RED;
26+
/// 'Green' RgbColor (0, 255, 0)
27+
static ColorBgr GREEN;
28+
/// 'Blue' RgbColor (0, 0, 255)
29+
static ColorBgr BLUE;
30+
/// 'Yellow' RgbColor (255, 255, 0)
31+
static ColorBgr YELLOW;
32+
/// 'White' RgbColor (255, 255, 255)
33+
static ColorBgr WHITE;
34+
};
35+
36+
/// Assert to ensure that the size of the structure is 'only' 3 bytes
37+
static_assert(sizeof(ColorBgr) == 3, "Incorrect size of ColorRgb");
38+
39+
///
40+
/// Stream operator to write ColorRgb to an outputstream (format "'{'[red]','[green]','[blue]'}'")
41+
///
42+
/// @param os The output stream
43+
/// @param color The color to write
44+
/// @return The output stream (with the color written to it)
45+
///
46+
inline std::ostream& operator<<(std::ostream& os, const ColorBgr& color)
47+
{
48+
os << "{" << unsigned(color.red) << "," << unsigned(color.green) << "," << unsigned(color.blue) << "}";
49+
return os;
50+
}
51+
52+
53+
/// Compare operator to check if a color is 'smaller' than another color
54+
inline bool operator<(const ColorBgr & lhs, const ColorBgr & rhs)
55+
{
56+
return (lhs.red < rhs.red) && (lhs.green < rhs.green) && (lhs.blue < rhs.blue);
57+
}
58+
59+
/// Compare operator to check if a color is 'smaller' than or 'equal' to another color
60+
inline bool operator<=(const ColorBgr & lhs, const ColorBgr & rhs)
61+
{
62+
return (lhs.red <= rhs.red) && (lhs.green <= rhs.green) && (lhs.blue <= rhs.blue);
63+
}

libsrc/grabber/amlogic/AmlogicGrabber.cpp

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
// STL includes
3+
#include <algorithm>
34
#include <cassert>
45
#include <iostream>
56

@@ -14,16 +15,22 @@
1415
// Local includes
1516
#include "AmlogicGrabber.h"
1617

17-
// Flags copied from 'linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic/
18+
// Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic
1819
#define AMVIDEOCAP_IOC_MAGIC 'V'
19-
#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW(AMVIDEOCAP_IOC_MAGIC, 0x02, int)
20-
#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW(AMVIDEOCAP_IOC_MAGIC, 0x03, int)
20+
#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW(AMVIDEOCAP_IOC_MAGIC, 0x02, int)
21+
#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW(AMVIDEOCAP_IOC_MAGIC, 0x03, int)
22+
23+
// Flags copied from 'include/linux/amlogic/amports/amvstream.h' at https://github.com/codesnake/linux-amlogic
24+
#define AMSTREAM_IOC_MAGIC 'S'
25+
#define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR(AMSTREAM_IOC_MAGIC, 0x48, unsigned long)
2126

2227
AmlogicGrabber::AmlogicGrabber(const unsigned width, const unsigned height) :
23-
_width(width),
24-
_height(height),
28+
// Minimum required width or height is 160
29+
_width(std::max(160u, width)),
30+
_height(std::max(160u, height)),
2531
_amlogicCaptureDev(-1)
2632
{
33+
std::cout << "[" << __PRETTY_FUNCTION__ << "] constructed(" << _width << "x" << _height << ")" << std::endl;
2734
}
2835

2936
AmlogicGrabber::~AmlogicGrabber()
@@ -54,40 +61,90 @@ void AmlogicGrabber::setVideoMode(const VideoMode videoMode)
5461
}
5562
}
5663

57-
void AmlogicGrabber::grabFrame(Image<ColorRgb> & image)
64+
bool AmlogicGrabber::isVideoPlaying()
65+
{
66+
const std::string videoDevice = "/dev/amvideo";
67+
68+
// Open the video device
69+
int video_fd = open(videoDevice.c_str(), O_RDONLY);
70+
if (video_fd < 0)
71+
{
72+
std::cerr << "Failed to open video device(" << videoDevice << "): " << strerror(errno) << std::endl;
73+
return false;
74+
}
75+
76+
// Check the video disabled flag
77+
int videoDisabled;
78+
if (ioctl(video_fd, AMSTREAM_IOC_GET_VIDEO_DISABLE, &videoDisabled) == -1)
79+
{
80+
std::cerr << "Failed to retrieve video state from device: " << strerror(errno) << std::endl;
81+
close(video_fd);
82+
return false;
83+
}
84+
85+
// Make sure to close the device after use
86+
close(video_fd);
87+
88+
return videoDisabled == 0;
89+
}
90+
91+
int AmlogicGrabber::grabFrame(Image<ColorBgr> & image)
5892
{
5993
// resize the given image if needed
6094
if (image.width() != _width || image.height() != _height)
6195
{
6296
image.resize(_width, _height);
6397
}
64-
65-
_amlogicCaptureDev = open("/dev/amvideocap0", O_RDONLY, 0);
98+
99+
// Make sure video is playing, else there is nothing to grab
100+
if (!isVideoPlaying())
101+
{
102+
return -1;
103+
}
104+
105+
106+
// If the device is not open, attempt to open it
66107
if (_amlogicCaptureDev == -1)
67108
{
68-
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Failed to open the AMLOGIC device (" << errno << ")" << std::endl;
69-
return;
109+
_amlogicCaptureDev = open("/dev/amvideocap0", O_RDONLY, 0);
110+
111+
// If the device is still not open, there is something wrong
112+
if (_amlogicCaptureDev == -1)
113+
{
114+
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Failed to open the AMLOGIC device (" << errno << "): " << strerror(errno) << std::endl;
115+
return -1;
116+
}
70117
}
71-
72-
if (ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH, _width) == -1 ||
73-
ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT, _height) == -1)
118+
119+
120+
if (ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH, _width) == -1 ||
121+
ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT, _height) == -1)
74122
{
75123
// Failed to configure frame width
76-
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Failed to configure capture size (" << errno << ")" << std::endl;
77-
return;
124+
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Failed to configure capture size (" << errno << "): " << strerror(errno) << std::endl;
125+
return -1;
78126
}
79-
80-
std::cout << "AMLOGIC grabber created (size " << _width << "x" << _height << ")" << std::endl;
127+
81128
// Read the snapshot into the memory
82129
void * image_ptr = image.memptr();
83-
const size_t bytesToRead = _width * _height * sizeof(ColorRgb);
84-
const size_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0);
85-
if (bytesToRead != bytesRead)
130+
const ssize_t bytesToRead = _width * _height * sizeof(ColorBgr);
131+
132+
const ssize_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0);
133+
if (bytesRead == -1)
134+
{
135+
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Read of device failed (erno=" << errno << "): " << strerror(errno) << std::endl;
136+
return -1;
137+
}
138+
else if (bytesToRead != bytesRead)
86139
{
87140
// Read of snapshot failed
88141
std::cerr << "[" << __PRETTY_FUNCTION__ << "] Capture failed to grab entire image [bytesToRead(" << bytesToRead << ") != bytesRead(" << bytesRead << ")]" << std::endl;
142+
return -1;
89143
}
90-
144+
145+
// For now we always close the device again
91146
close(_amlogicCaptureDev);
92147
_amlogicCaptureDev = -1;
148+
149+
return 0;
93150
}

libsrc/grabber/amlogic/AmlogicGrabber.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
// Utils includes
77
#include <utils/Image.h>
8-
#include <utils/ColorRgb.h>
8+
#include <utils/ColorBgr.h>
99
#include <utils/VideoMode.h>
1010

1111
///
@@ -37,16 +37,22 @@ class AmlogicGrabber
3737
///
3838
/// @param[out] image The snapped screenshot (should be initialized with correct width and
3939
/// height)
40+
/// @return Zero on success else negative
4041
///
41-
void grabFrame(Image<ColorRgb> & image);
42+
int grabFrame(Image<ColorBgr> & image);
4243

44+
/**
45+
* Returns true if video is playing over the amlogic chip
46+
* @return True if video is playing else false
47+
*/
48+
bool isVideoPlaying();
4349
private:
4450

4551
/// With of the captured snapshot [pixels]
4652
const unsigned _width;
4753
/// Height of the captured snapshot [pixels]
4854
const unsigned _height;
49-
55+
5056
/** The snapshot/capture device of the amlogic video chip */
5157
int _amlogicCaptureDev;
5258
};

libsrc/grabber/amlogic/AmlogicWrapper.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) :
1616
_updateInterval_ms(1000/updateRate_Hz),
1717
_timeout_ms(2 * _updateInterval_ms),
18-
_priority(1000),
18+
_priority(999),
1919
_timer(),
2020
_image(grabWidth, grabHeight),
2121
_frameGrabber(new AmlogicGrabber(grabWidth, grabHeight)),
@@ -49,12 +49,17 @@ void AmlogicWrapper::start()
4949
void AmlogicWrapper::action()
5050
{
5151
// Grab frame into the allocated image
52-
_frameGrabber->grabFrame(_image);
52+
if (_frameGrabber->grabFrame(_image) < 0)
53+
{
54+
// Frame grab failed, maybe nothing playing or ....
55+
return;
56+
}
5357

5458
_processor->process(_image, _ledColors);
5559

5660
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
5761
}
62+
5863
void AmlogicWrapper::stop()
5964
{
6065
// Stop the timer, effectivly stopping the process

libsrc/utils/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/utils)
66
add_library(hyperion-utils
77
${CURRENT_HEADER_DIR}/ColorArgb.h
88
${CURRENT_SOURCE_DIR}/ColorArgb.cpp
9+
${CURRENT_HEADER_DIR}/ColorBgr.h
10+
${CURRENT_SOURCE_DIR}/ColorBgr.cpp
911
${CURRENT_HEADER_DIR}/ColorRgb.h
1012
${CURRENT_SOURCE_DIR}/ColorRgb.cpp
1113
${CURRENT_HEADER_DIR}/ColorRgba.h

libsrc/utils/ColorBgr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
// Local includes
3+
#include <utils/ColorBgr.h>
4+
5+
ColorBgr ColorBgr::BLACK = { 0, 0, 0 };
6+
ColorBgr ColorBgr::RED = { 0, 0, 255 };
7+
ColorBgr ColorBgr::GREEN = { 0, 255, 0 };
8+
ColorBgr ColorBgr::BLUE = { 255, 0, 0 };
9+
ColorBgr ColorBgr::YELLOW= { 0, 255, 255 };
10+
ColorBgr ColorBgr::WHITE = { 255, 255, 255 };
11+

src/hyperion-aml/hyperion-aml.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
using namespace vlofgren;
1313

1414
// save the image as screenshot
15-
void saveScreenshot(const char * filename, const Image<ColorRgb> & image)
15+
void saveScreenshot(const char * filename, const Image<ColorBgr> & image)
1616
{
17-
// store as PNG
18-
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
19-
pngImage.save(filename);
17+
// store as PNG
18+
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
19+
pngImage = pngImage.rgbSwapped();
20+
pngImage.save(filename);
2021
}
2122

2223
int main(int argc, char ** argv)
@@ -39,11 +40,11 @@ int main(int argc, char ** argv)
3940
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
4041

4142
// set defaults
42-
argWidth.setDefault(64);
43-
argHeight.setDefault(64);
43+
argWidth.setDefault(160);
44+
argHeight.setDefault(160);
4445
argAddress.setDefault("127.0.0.1:19445");
4546
argPriority.setDefault(800);
46-
47+
4748
// parse all options
4849
optionParser.parse(argc, const_cast<const char **>(argv));
4950

@@ -54,19 +55,29 @@ int main(int argc, char ** argv)
5455
return 0;
5556
}
5657

58+
int width = argWidth.getValue();
59+
int height = argHeight.getValue();
60+
if (width < 160 || height < 60)
61+
{
62+
std::cout << "Minimum width and height is 160" << std::endl;
63+
width = std::max(160, width);
64+
height = std::max(160, height);
65+
}
5766
if (argScreenshot.isSet())
5867
{
68+
5969
// Create the grabber
60-
AmlogicGrabber amlGrabber(argWidth.getValue(), argHeight.getValue());
61-
70+
AmlogicGrabber amlGrabber(width, height);
71+
6272
// Capture a single screenshot and finish
63-
Image<ColorRgb> screenshot;
73+
Image<ColorBgr> screenshot;
6474
amlGrabber.grabFrame(screenshot);
6575
saveScreenshot("screenshot.png", screenshot);
6676
}
6777
else
6878
{
6979
// TODO[TvdZ]: Implement the proto-client mechanisme
80+
std::cerr << "The PROTO-interface has not been implemented yet" << std::endl;
7081
}
7182

7283
}

src/hyperiond/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ if (ENABLE_V4L2)
2626
target_link_libraries(hyperiond v4l2-grabber)
2727
endif (ENABLE_V4L2)
2828

29+
if (ENABLE_AMLOGIC)
30+
target_link_libraries(hyperiond amlogic-grabber)
31+
endif (ENABLE_AMLOGIC)
32+
2933
if (ENABLE_PROTOBUF)
3034
target_link_libraries(hyperiond protoserver)
3135
endif (ENABLE_PROTOBUF)

0 commit comments

Comments
 (0)