mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-15 03:53:43 +00:00
refactoring
This commit is contained in:
@@ -296,8 +296,8 @@ int device_grab_buffer(struct device_t *dev) {
|
|||||||
|
|
||||||
// Workaround for broken, corrupted frames:
|
// Workaround for broken, corrupted frames:
|
||||||
// Under low light conditions corrupted frames may get captured.
|
// Under low light conditions corrupted frames may get captured.
|
||||||
// The good thing is such frames are quite small compared to the regular pictures.
|
// The good thing is such frames are quite small compared to the regular frames.
|
||||||
// For example a VGA (640x480) webcam picture is normally >= 8kByte large,
|
// For example a VGA (640x480) webcam frame is normally >= 8kByte large,
|
||||||
// corrupted frames are smaller.
|
// corrupted frames are smaller.
|
||||||
if (buf_info.bytesused < dev->min_frame_size) {
|
if (buf_info.bytesused < dev->min_frame_size) {
|
||||||
LOG_DEBUG("Dropped too small frame sized %d bytes, assuming it was broken", buf_info.bytesused);
|
LOG_DEBUG("Dropped too small frame sized %d bytes, assuming it was broken", buf_info.bytesused);
|
||||||
|
|||||||
@@ -209,26 +209,26 @@ void encoder_get_runtime_params(struct encoder_t *encoder, enum encoder_type_t *
|
|||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
int encoder_compress_buffer(
|
int encoder_compress_buffer(
|
||||||
struct encoder_t *encoder, unsigned worker_number,
|
struct encoder_t *encoder, unsigned worker_number,
|
||||||
struct hw_buffer_t *hw, struct picture_t *picture) {
|
struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
|
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
|
||||||
assert(hw->used > 0);
|
assert(hw->used > 0);
|
||||||
|
|
||||||
picture->grab_ts = hw->grab_ts;
|
frame->grab_ts = hw->grab_ts;
|
||||||
picture->encode_begin_ts = get_now_monotonic();
|
frame->encode_begin_ts = get_now_monotonic();
|
||||||
|
|
||||||
if (ER(type) == ENCODER_TYPE_CPU) {
|
if (ER(type) == ENCODER_TYPE_CPU) {
|
||||||
LOG_VERBOSE("Compressing buffer using CPU");
|
LOG_VERBOSE("Compressing buffer using CPU");
|
||||||
cpu_encoder_compress_buffer(hw, picture, ER(quality));
|
cpu_encoder_compress_buffer(hw, frame, ER(quality));
|
||||||
} else if (ER(type) == ENCODER_TYPE_HW) {
|
} else if (ER(type) == ENCODER_TYPE_HW) {
|
||||||
LOG_VERBOSE("Compressing buffer using HW (just copying)");
|
LOG_VERBOSE("Compressing buffer using HW (just copying)");
|
||||||
hw_encoder_compress_buffer(hw, picture);
|
hw_encoder_compress_buffer(hw, frame);
|
||||||
}
|
}
|
||||||
# ifdef WITH_OMX
|
# ifdef WITH_OMX
|
||||||
else if (ER(type) == ENCODER_TYPE_OMX) {
|
else if (ER(type) == ENCODER_TYPE_OMX) {
|
||||||
LOG_VERBOSE("Compressing buffer using OMX");
|
LOG_VERBOSE("Compressing buffer using OMX");
|
||||||
if (omx_encoder_compress_buffer(ER(omxs[worker_number]), hw, picture) < 0) {
|
if (omx_encoder_compress_buffer(ER(omxs[worker_number]), hw, frame) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,10 +240,10 @@ int encoder_compress_buffer(
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
picture->encode_end_ts = get_now_monotonic();
|
frame->encode_end_ts = get_now_monotonic();
|
||||||
|
|
||||||
picture->width = hw->width;
|
frame->width = hw->width;
|
||||||
picture->height = hw->height;
|
frame->height = hw->height;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "../common/logging.h"
|
#include "../common/logging.h"
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "picture.h"
|
#include "frame.h"
|
||||||
|
|
||||||
#include "encoders/cpu/encoder.h"
|
#include "encoders/cpu/encoder.h"
|
||||||
#include "encoders/hw/encoder.h"
|
#include "encoders/hw/encoder.h"
|
||||||
@@ -113,4 +113,4 @@ void encoder_get_runtime_params(struct encoder_t *encoder, enum encoder_type_t *
|
|||||||
|
|
||||||
int encoder_compress_buffer(
|
int encoder_compress_buffer(
|
||||||
struct encoder_t *encoder, unsigned worker_number,
|
struct encoder_t *encoder, unsigned worker_number,
|
||||||
struct hw_buffer_t *hw, struct picture_t *picture);
|
struct hw_buffer_t *hw, struct frame_t *frame);
|
||||||
|
|||||||
@@ -31,11 +31,11 @@
|
|||||||
struct _jpeg_dest_manager_t {
|
struct _jpeg_dest_manager_t {
|
||||||
struct jpeg_destination_mgr mgr; // Default manager
|
struct jpeg_destination_mgr mgr; // Default manager
|
||||||
JOCTET *buffer; // Start of buffer
|
JOCTET *buffer; // Start of buffer
|
||||||
struct picture_t *picture;
|
struct frame_t *frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void _jpeg_set_picture(j_compress_ptr jpeg, struct picture_t *picture);
|
static void _jpeg_set_picture(j_compress_ptr jpeg, struct frame_t *frame);
|
||||||
|
|
||||||
static void _jpeg_write_scanlines_yuyv(
|
static void _jpeg_write_scanlines_yuyv(
|
||||||
struct jpeg_compress_struct *jpeg, const unsigned char *data,
|
struct jpeg_compress_struct *jpeg, const unsigned char *data,
|
||||||
@@ -58,7 +58,7 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg);
|
|||||||
static void _jpeg_term_destination(j_compress_ptr jpeg);
|
static void _jpeg_term_destination(j_compress_ptr jpeg);
|
||||||
|
|
||||||
|
|
||||||
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *picture, unsigned quality) {
|
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame, unsigned quality) {
|
||||||
// This function based on compress_image_to_jpeg() from mjpg-streamer
|
// This function based on compress_image_to_jpeg() from mjpg-streamer
|
||||||
|
|
||||||
struct jpeg_compress_struct jpeg;
|
struct jpeg_compress_struct jpeg;
|
||||||
@@ -67,7 +67,7 @@ void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *pictu
|
|||||||
jpeg.err = jpeg_std_error(&jpeg_error);
|
jpeg.err = jpeg_std_error(&jpeg_error);
|
||||||
jpeg_create_compress(&jpeg);
|
jpeg_create_compress(&jpeg);
|
||||||
|
|
||||||
_jpeg_set_picture(&jpeg, picture);
|
_jpeg_set_picture(&jpeg, frame);
|
||||||
|
|
||||||
jpeg.image_width = hw->width;
|
jpeg.image_width = hw->width;
|
||||||
jpeg.image_height = hw->height;
|
jpeg.image_height = hw->height;
|
||||||
@@ -96,10 +96,10 @@ void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *pictu
|
|||||||
jpeg_finish_compress(&jpeg);
|
jpeg_finish_compress(&jpeg);
|
||||||
jpeg_destroy_compress(&jpeg);
|
jpeg_destroy_compress(&jpeg);
|
||||||
|
|
||||||
assert(picture->used > 0);
|
assert(frame->used > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _jpeg_set_picture(j_compress_ptr jpeg, struct picture_t *picture) {
|
static void _jpeg_set_picture(j_compress_ptr jpeg, struct frame_t *frame) {
|
||||||
struct _jpeg_dest_manager_t *dest;
|
struct _jpeg_dest_manager_t *dest;
|
||||||
|
|
||||||
if (jpeg->dest == NULL) {
|
if (jpeg->dest == NULL) {
|
||||||
@@ -112,9 +112,9 @@ static void _jpeg_set_picture(j_compress_ptr jpeg, struct picture_t *picture) {
|
|||||||
dest->mgr.init_destination = _jpeg_init_destination;
|
dest->mgr.init_destination = _jpeg_init_destination;
|
||||||
dest->mgr.empty_output_buffer = _jpeg_empty_output_buffer;
|
dest->mgr.empty_output_buffer = _jpeg_empty_output_buffer;
|
||||||
dest->mgr.term_destination = _jpeg_term_destination;
|
dest->mgr.term_destination = _jpeg_term_destination;
|
||||||
dest->picture = picture;
|
dest->frame = frame;
|
||||||
|
|
||||||
picture->used = 0;
|
frame->used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define YUV_R(_y, _, _v) (((_y) + (359 * (_v))) >> 8)
|
#define YUV_R(_y, _, _v) (((_y) + (359 * (_v))) >> 8)
|
||||||
@@ -265,7 +265,7 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg) {
|
|||||||
|
|
||||||
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
||||||
|
|
||||||
picture_append_data(dest->picture, dest->buffer, JPEG_OUTPUT_BUFFER_SIZE);
|
frame_append_data(dest->frame, dest->buffer, JPEG_OUTPUT_BUFFER_SIZE);
|
||||||
|
|
||||||
dest->mgr.next_output_byte = dest->buffer;
|
dest->mgr.next_output_byte = dest->buffer;
|
||||||
dest->mgr.free_in_buffer = JPEG_OUTPUT_BUFFER_SIZE;
|
dest->mgr.free_in_buffer = JPEG_OUTPUT_BUFFER_SIZE;
|
||||||
@@ -281,7 +281,7 @@ static void _jpeg_term_destination(j_compress_ptr jpeg) {
|
|||||||
size_t final = JPEG_OUTPUT_BUFFER_SIZE - dest->mgr.free_in_buffer;
|
size_t final = JPEG_OUTPUT_BUFFER_SIZE - dest->mgr.free_in_buffer;
|
||||||
|
|
||||||
// Write any data remaining in the buffer.
|
// Write any data remaining in the buffer.
|
||||||
picture_append_data(dest->picture, dest->buffer, final);
|
frame_append_data(dest->frame, dest->buffer, final);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef JPEG_OUTPUT_BUFFER_SIZE
|
#undef JPEG_OUTPUT_BUFFER_SIZE
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
#include "../../../common/tools.h"
|
#include "../../../common/tools.h"
|
||||||
#include "../../picture.h"
|
#include "../../frame.h"
|
||||||
#include "../../device.h"
|
#include "../../device.h"
|
||||||
|
|
||||||
|
|
||||||
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *picture, unsigned quality);
|
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame, unsigned quality);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
|
|
||||||
|
|
||||||
void _copy_plus_huffman(const struct hw_buffer_t *src, struct picture_t *dest);
|
void _copy_plus_huffman(const struct hw_buffer_t *src, struct frame_t *dest);
|
||||||
static bool _is_huffman(const unsigned char *data);
|
static bool _is_huffman(const unsigned char *data);
|
||||||
|
|
||||||
|
|
||||||
@@ -49,14 +49,14 @@ int hw_encoder_prepare(struct device_t *dev, unsigned quality) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *picture) {
|
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||||
if (hw->format != V4L2_PIX_FMT_MJPEG && hw->format != V4L2_PIX_FMT_JPEG) {
|
if (hw->format != V4L2_PIX_FMT_MJPEG && hw->format != V4L2_PIX_FMT_JPEG) {
|
||||||
assert(0 && "Unsupported input format for HW encoder");
|
assert(0 && "Unsupported input format for HW encoder");
|
||||||
}
|
}
|
||||||
_copy_plus_huffman(hw, picture);
|
_copy_plus_huffman(hw, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _copy_plus_huffman(const struct hw_buffer_t *src, struct picture_t *dest) {
|
void _copy_plus_huffman(const struct hw_buffer_t *src, struct frame_t *dest) {
|
||||||
if (!_is_huffman(src->data)) {
|
if (!_is_huffman(src->data)) {
|
||||||
const unsigned char *src_ptr = src->data;
|
const unsigned char *src_ptr = src->data;
|
||||||
const unsigned char *src_end = src->data + src->used;
|
const unsigned char *src_end = src->data + src->used;
|
||||||
@@ -71,11 +71,11 @@ void _copy_plus_huffman(const struct hw_buffer_t *src, struct picture_t *dest) {
|
|||||||
}
|
}
|
||||||
paste = src_ptr - src->data;
|
paste = src_ptr - src->data;
|
||||||
|
|
||||||
picture_set_data(dest, src->data, paste);
|
frame_set_data(dest, src->data, paste);
|
||||||
picture_append_data(dest, HUFFMAN_TABLE, sizeof(HUFFMAN_TABLE));
|
frame_append_data(dest, HUFFMAN_TABLE, sizeof(HUFFMAN_TABLE));
|
||||||
picture_append_data(dest, src_ptr, src->used - paste);
|
frame_append_data(dest, src_ptr, src->used - paste);
|
||||||
} else {
|
} else {
|
||||||
picture_set_data(dest, src->data, src->used);
|
frame_set_data(dest, src->data, src->used);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,11 +31,11 @@
|
|||||||
#include "../../../common/tools.h"
|
#include "../../../common/tools.h"
|
||||||
#include "../../../common/logging.h"
|
#include "../../../common/logging.h"
|
||||||
#include "../../xioctl.h"
|
#include "../../xioctl.h"
|
||||||
#include "../../picture.h"
|
#include "../../frame.h"
|
||||||
#include "../../device.h"
|
#include "../../device.h"
|
||||||
|
|
||||||
#include "huffman.h"
|
#include "huffman.h"
|
||||||
|
|
||||||
|
|
||||||
int hw_encoder_prepare(struct device_t *dev, unsigned quality);
|
int hw_encoder_prepare(struct device_t *dev, unsigned quality);
|
||||||
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct picture_t *picture);
|
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigne
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct picture_t *picture) {
|
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||||
# define IN(_next) omx->input_buffer->_next
|
# define IN(_next) omx->input_buffer->_next
|
||||||
# define OUT(_next) omx->output_buffer->_next
|
# define OUT(_next) omx->output_buffer->_next
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *h
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
picture->used = 0;
|
frame->used = 0;
|
||||||
omx->output_available = false;
|
omx->output_available = false;
|
||||||
omx->input_required = true;
|
omx->input_required = true;
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *h
|
|||||||
if (omx->output_available) {
|
if (omx->output_available) {
|
||||||
omx->output_available = false;
|
omx->output_available = false;
|
||||||
|
|
||||||
picture_append_data(picture, OUT(pBuffer) + OUT(nOffset), OUT(nFilledLen));
|
frame_append_data(frame, OUT(pBuffer) + OUT(nOffset), OUT(nFilledLen));
|
||||||
|
|
||||||
if (OUT(nFlags) & OMX_BUFFERFLAG_ENDOFFRAME) {
|
if (OUT(nFlags) & OMX_BUFFERFLAG_ENDOFFRAME) {
|
||||||
OUT(nFlags) = 0;
|
OUT(nFlags) = 0;
|
||||||
@@ -322,7 +322,7 @@ static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) {
|
|||||||
portdef.format.image.nSliceHeight = align_size(dev->run->height, 16);
|
portdef.format.image.nSliceHeight = align_size(dev->run->height, 16);
|
||||||
portdef.format.image.bFlagErrorConcealment = OMX_FALSE;
|
portdef.format.image.bFlagErrorConcealment = OMX_FALSE;
|
||||||
portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
|
portdef.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
|
||||||
portdef.nBufferSize = picture_get_generous_size(dev->run->width, dev->run->height);
|
portdef.nBufferSize = frame_get_generous_size(dev->run->width, dev->run->height);
|
||||||
|
|
||||||
# define MAP_FORMAT(_v4l2_format, _omx_format) \
|
# define MAP_FORMAT(_v4l2_format, _omx_format) \
|
||||||
case _v4l2_format: { portdef.format.image.eColorFormat = _omx_format; break; }
|
case _v4l2_format: { portdef.format.image.eColorFormat = _omx_format; break; }
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#include "../../../common/logging.h"
|
#include "../../../common/logging.h"
|
||||||
#include "../../../common/tools.h"
|
#include "../../../common/tools.h"
|
||||||
#include "../../device.h"
|
#include "../../device.h"
|
||||||
#include "../../picture.h"
|
#include "../../frame.h"
|
||||||
|
|
||||||
#include "formatters.h"
|
#include "formatters.h"
|
||||||
#include "component.h"
|
#include "component.h"
|
||||||
@@ -71,4 +71,4 @@ struct omx_encoder_t *omx_encoder_init(void);
|
|||||||
void omx_encoder_destroy(struct omx_encoder_t *omx);
|
void omx_encoder_destroy(struct omx_encoder_t *omx);
|
||||||
|
|
||||||
int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigned quality);
|
int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigned quality);
|
||||||
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct picture_t *picture);
|
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct frame_t *frame);
|
||||||
|
|||||||
@@ -20,52 +20,52 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "picture.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
|
||||||
struct picture_t *picture_init(void) {
|
struct frame_t *frame_init(void) {
|
||||||
struct picture_t *picture;
|
struct frame_t *frame;
|
||||||
|
|
||||||
A_CALLOC(picture, 1);
|
A_CALLOC(frame, 1);
|
||||||
return picture;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_destroy(struct picture_t *picture) {
|
void frame_destroy(struct frame_t *frame) {
|
||||||
if (picture->data) {
|
if (frame->data) {
|
||||||
free(picture->data);
|
free(frame->data);
|
||||||
}
|
}
|
||||||
free(picture);
|
free(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t picture_get_generous_size(unsigned width, unsigned height) {
|
size_t frame_get_generous_size(unsigned width, unsigned height) {
|
||||||
return ((width * height) << 1) * 2;
|
return ((width * height) << 1) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_realloc_data(struct picture_t *picture, size_t size) {
|
void frame_realloc_data(struct frame_t *frame, size_t size) {
|
||||||
if (picture->allocated < size) {
|
if (frame->allocated < size) {
|
||||||
LOG_DEBUG("Increasing picture %p buffer: %zu -> %zu (+%zu)",
|
LOG_DEBUG("Increasing frame %p buffer: %zu -> %zu (+%zu)",
|
||||||
picture, picture->allocated, size, size - picture->allocated);
|
frame, frame->allocated, size, size - frame->allocated);
|
||||||
A_REALLOC(picture->data, size);
|
A_REALLOC(frame->data, size);
|
||||||
picture->allocated = size;
|
frame->allocated = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_set_data(struct picture_t *picture, const unsigned char *data, size_t size) {
|
void frame_set_data(struct frame_t *frame, const unsigned char *data, size_t size) {
|
||||||
picture_realloc_data(picture, size);
|
frame_realloc_data(frame, size);
|
||||||
memcpy(picture->data, data, size);
|
memcpy(frame->data, data, size);
|
||||||
picture->used = size;
|
frame->used = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_append_data(struct picture_t *picture, const unsigned char *data, size_t size) {
|
void frame_append_data(struct frame_t *frame, const unsigned char *data, size_t size) {
|
||||||
size_t new_used = picture->used + size;
|
size_t new_used = frame->used + size;
|
||||||
|
|
||||||
picture_realloc_data(picture, new_used);
|
frame_realloc_data(frame, new_used);
|
||||||
memcpy(picture->data + picture->used, data, size);
|
memcpy(frame->data + frame->used, data, size);
|
||||||
picture->used = new_used;
|
frame->used = new_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picture_copy(const struct picture_t *src, struct picture_t *dest) {
|
void frame_copy(const struct frame_t *src, struct frame_t *dest) {
|
||||||
picture_set_data(dest, src->data, src->used);
|
frame_set_data(dest, src->data, src->used);
|
||||||
|
|
||||||
# define COPY(_field) dest->_field = src->_field
|
# define COPY(_field) dest->_field = src->_field
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ void picture_copy(const struct picture_t *src, struct picture_t *dest) {
|
|||||||
# undef COPY
|
# undef COPY
|
||||||
}
|
}
|
||||||
|
|
||||||
bool picture_compare(const struct picture_t *a, const struct picture_t *b) {
|
bool frame_compare(const struct frame_t *a, const struct frame_t *b) {
|
||||||
return (
|
return (
|
||||||
a->allocated && b->allocated
|
a->allocated && b->allocated
|
||||||
&& a->used == b->used
|
&& a->used == b->used
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "../common/logging.h"
|
#include "../common/logging.h"
|
||||||
|
|
||||||
|
|
||||||
struct picture_t {
|
struct frame_t {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t allocated;
|
size_t allocated;
|
||||||
@@ -44,14 +44,14 @@ struct picture_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct picture_t *picture_init(void);
|
struct frame_t *frame_init(void);
|
||||||
void picture_destroy(struct picture_t *picture);
|
void frame_destroy(struct frame_t *frame);
|
||||||
|
|
||||||
size_t picture_get_generous_size(unsigned width, unsigned height);
|
size_t frame_get_generous_size(unsigned width, unsigned height);
|
||||||
|
|
||||||
void picture_realloc_data(struct picture_t *picture, size_t size);
|
void frame_realloc_data(struct frame_t *frame, size_t size);
|
||||||
void picture_set_data(struct picture_t *picture, const unsigned char *data, size_t size);
|
void frame_set_data(struct frame_t *frame, const unsigned char *data, size_t size);
|
||||||
void picture_append_data(struct picture_t *picture, const unsigned char *data, size_t size);
|
void frame_append_data(struct frame_t *frame, const unsigned char *data, size_t size);
|
||||||
|
|
||||||
void picture_copy(const struct picture_t *src, struct picture_t *dest);
|
void frame_copy(const struct frame_t *src, struct frame_t *dest);
|
||||||
bool picture_compare(const struct picture_t *a, const struct picture_t *b);
|
bool frame_compare(const struct frame_t *a, const struct frame_t *b);
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include "../../common/tools.h"
|
#include "../../common/tools.h"
|
||||||
#include "../../common/logging.h"
|
#include "../../common/logging.h"
|
||||||
#include "../picture.h"
|
#include "../frame.h"
|
||||||
|
|
||||||
#include "data/blank_jpeg.h"
|
#include "data/blank_jpeg.h"
|
||||||
|
|
||||||
@@ -41,15 +41,15 @@ struct _jpeg_error_manager_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct picture_t *_init_internal(void);
|
static struct frame_t *_init_internal(void);
|
||||||
static struct picture_t *_init_external(const char *path);
|
static struct frame_t *_init_external(const char *path);
|
||||||
|
|
||||||
static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height);
|
static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height);
|
||||||
static void _jpeg_error_handler(j_common_ptr jpeg);
|
static void _jpeg_error_handler(j_common_ptr jpeg);
|
||||||
|
|
||||||
|
|
||||||
struct picture_t *blank_picture_init(const char *path) {
|
struct frame_t *blank_picture_init(const char *path) {
|
||||||
struct picture_t *blank = NULL;
|
struct frame_t *blank = NULL;
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
blank = _init_external(path);
|
blank = _init_external(path);
|
||||||
@@ -64,21 +64,21 @@ struct picture_t *blank_picture_init(const char *path) {
|
|||||||
return blank;
|
return blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct picture_t *_init_internal(void) {
|
static struct frame_t *_init_internal(void) {
|
||||||
struct picture_t *blank;
|
struct frame_t *blank;
|
||||||
|
|
||||||
blank = picture_init();
|
blank = frame_init();
|
||||||
picture_set_data(blank, BLANK_JPEG_DATA, ARRAY_LEN(BLANK_JPEG_DATA));
|
frame_set_data(blank, BLANK_JPEG_DATA, ARRAY_LEN(BLANK_JPEG_DATA));
|
||||||
blank->width = BLANK_JPEG_WIDTH;
|
blank->width = BLANK_JPEG_WIDTH;
|
||||||
blank->height = BLANK_JPEG_HEIGHT;
|
blank->height = BLANK_JPEG_HEIGHT;
|
||||||
return blank;
|
return blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct picture_t *_init_external(const char *path) {
|
static struct frame_t *_init_external(const char *path) {
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
struct picture_t *blank;
|
struct frame_t *blank;
|
||||||
|
|
||||||
blank = picture_init();
|
blank = frame_init();
|
||||||
|
|
||||||
if ((fp = fopen(path, "rb")) == NULL) {
|
if ((fp = fopen(path, "rb")) == NULL) {
|
||||||
LOG_PERROR("Can't open blank placeholder '%s'", path);
|
LOG_PERROR("Can't open blank placeholder '%s'", path);
|
||||||
@@ -97,7 +97,7 @@ static struct picture_t *_init_external(const char *path) {
|
|||||||
# define CHUNK_SIZE ((size_t)(100 * 1024))
|
# define CHUNK_SIZE ((size_t)(100 * 1024))
|
||||||
while (true) {
|
while (true) {
|
||||||
if (blank->used + CHUNK_SIZE >= blank->allocated) {
|
if (blank->used + CHUNK_SIZE >= blank->allocated) {
|
||||||
picture_realloc_data(blank, blank->used + CHUNK_SIZE * 2);
|
frame_realloc_data(blank, blank->used + CHUNK_SIZE * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readed = fread(blank->data + blank->used, 1, CHUNK_SIZE, fp);
|
size_t readed = fread(blank->data + blank->used, 1, CHUNK_SIZE, fp);
|
||||||
@@ -115,7 +115,7 @@ static struct picture_t *_init_external(const char *path) {
|
|||||||
# undef CHUNK_SIZE
|
# undef CHUNK_SIZE
|
||||||
|
|
||||||
error:
|
error:
|
||||||
picture_destroy(blank);
|
frame_destroy(blank);
|
||||||
blank = NULL;
|
blank = NULL;
|
||||||
|
|
||||||
ok:
|
ok:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../picture.h"
|
#include "../frame.h"
|
||||||
|
|
||||||
|
|
||||||
struct picture_t *blank_picture_init(const char *path);
|
struct frame_t *blank_picture_init(const char *path);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
#include "../../common/threading.h"
|
#include "../../common/threading.h"
|
||||||
#include "../../common/logging.h"
|
#include "../../common/logging.h"
|
||||||
#include "../../common/process.h"
|
#include "../../common/process.h"
|
||||||
#include "../picture.h"
|
#include "../frame.h"
|
||||||
#include "../encoder.h"
|
#include "../encoder.h"
|
||||||
#include "../stream.h"
|
#include "../stream.h"
|
||||||
#ifdef WITH_GPIO
|
#ifdef WITH_GPIO
|
||||||
@@ -84,7 +84,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
|||||||
static void _http_callback_stream_error(struct bufferevent *buf_event, short what, void *v_ctx);
|
static void _http_callback_stream_error(struct bufferevent *buf_event, short what, void *v_ctx);
|
||||||
|
|
||||||
static void _http_exposed_refresh(int fd, short event, void *v_server);
|
static void _http_exposed_refresh(int fd, short event, void *v_server);
|
||||||
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool picture_updated);
|
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool frame_updated);
|
||||||
|
|
||||||
static bool _expose_new_picture_unsafe(struct http_server_t *server);
|
static bool _expose_new_picture_unsafe(struct http_server_t *server);
|
||||||
static bool _expose_blank_picture(struct http_server_t *server);
|
static bool _expose_blank_picture(struct http_server_t *server);
|
||||||
@@ -103,7 +103,7 @@ struct http_server_t *http_server_init(struct stream_t *stream) {
|
|||||||
struct exposed_t *exposed;
|
struct exposed_t *exposed;
|
||||||
|
|
||||||
A_CALLOC(exposed, 1);
|
A_CALLOC(exposed, 1);
|
||||||
exposed->picture = picture_init();
|
exposed->frame = frame_init();
|
||||||
|
|
||||||
A_CALLOC(run, 1);
|
A_CALLOC(run, 1);
|
||||||
run->stream = stream;
|
run->stream = stream;
|
||||||
@@ -158,10 +158,10 @@ void http_server_destroy(struct http_server_t *server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (RUN(blank)) {
|
if (RUN(blank)) {
|
||||||
picture_destroy(RUN(blank));
|
frame_destroy(RUN(blank));
|
||||||
}
|
}
|
||||||
|
|
||||||
picture_destroy(EX(picture));
|
frame_destroy(EX(frame));
|
||||||
free(RUN(exposed));
|
free(RUN(exposed));
|
||||||
free(server->run);
|
free(server->run);
|
||||||
free(server);
|
free(server);
|
||||||
@@ -184,13 +184,13 @@ int http_server_listen(struct http_server_t *server) {
|
|||||||
RUN(blank) = blank_picture_init(server->blank_path);
|
RUN(blank) = blank_picture_init(server->blank_path);
|
||||||
|
|
||||||
// See _expose_blank_picture()
|
// See _expose_blank_picture()
|
||||||
picture_copy(RUN(blank), EX(picture));
|
frame_copy(RUN(blank), EX(frame));
|
||||||
EX(expose_begin_ts) = get_now_monotonic();
|
EX(expose_begin_ts) = get_now_monotonic();
|
||||||
EX(expose_cmp_ts) = EX(expose_begin_ts);
|
EX(expose_cmp_ts) = EX(expose_begin_ts);
|
||||||
EX(expose_end_ts) = EX(expose_begin_ts);
|
EX(expose_end_ts) = EX(expose_begin_ts);
|
||||||
// See _http_exposed_refresh()
|
// See _http_exposed_refresh()
|
||||||
EX(notify_last_width) = EX(picture->width);
|
EX(notify_last_width) = EX(frame->width);
|
||||||
EX(notify_last_height) = EX(picture->height);
|
EX(notify_last_height) = EX(frame->height);
|
||||||
|
|
||||||
{
|
{
|
||||||
struct timeval refresh_interval;
|
struct timeval refresh_interval;
|
||||||
@@ -411,8 +411,8 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
|||||||
" \"stream\": {\"queued_fps\": %u, \"clients\": %u, \"clients_stat\": {",
|
" \"stream\": {\"queued_fps\": %u, \"clients\": %u, \"clients_stat\": {",
|
||||||
encoder_type_to_string(encoder_type),
|
encoder_type_to_string(encoder_type),
|
||||||
encoder_quality,
|
encoder_quality,
|
||||||
(server->fake_width ? server->fake_width : EX(picture->width)),
|
(server->fake_width ? server->fake_width : EX(frame->width)),
|
||||||
(server->fake_height ? server->fake_height : EX(picture->height)),
|
(server->fake_height ? server->fake_height : EX(frame->height)),
|
||||||
bool_to_string(EX(online)),
|
bool_to_string(EX(online)),
|
||||||
STREAM(dev->desired_fps),
|
STREAM(dev->desired_fps),
|
||||||
EX(captured_fps),
|
EX(captured_fps),
|
||||||
@@ -447,7 +447,7 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv
|
|||||||
PREPROCESS_REQUEST;
|
PREPROCESS_REQUEST;
|
||||||
|
|
||||||
assert((buf = evbuffer_new()));
|
assert((buf = evbuffer_new()));
|
||||||
assert(!evbuffer_add(buf, (const void *)EX(picture->data), EX(picture->used)));
|
assert(!evbuffer_add(buf, (const void *)EX(frame->data), EX(frame->used)));
|
||||||
|
|
||||||
if (server->allow_origin[0] != '\0') {
|
if (server->allow_origin[0] != '\0') {
|
||||||
ADD_HEADER("Access-Control-Allow-Origin", server->allow_origin);
|
ADD_HEADER("Access-Control-Allow-Origin", server->allow_origin);
|
||||||
@@ -470,11 +470,11 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv
|
|||||||
|
|
||||||
ADD_HEADER("X-UStreamer-Online", bool_to_string(EX(online)));
|
ADD_HEADER("X-UStreamer-Online", bool_to_string(EX(online)));
|
||||||
ADD_UNSIGNED_HEADER("X-UStreamer-Dropped", EX(dropped));
|
ADD_UNSIGNED_HEADER("X-UStreamer-Dropped", EX(dropped));
|
||||||
ADD_UNSIGNED_HEADER("X-UStreamer-Width", EX(picture->width));
|
ADD_UNSIGNED_HEADER("X-UStreamer-Width", EX(frame->width));
|
||||||
ADD_UNSIGNED_HEADER("X-UStreamer-Height", EX(picture->height));
|
ADD_UNSIGNED_HEADER("X-UStreamer-Height", EX(frame->height));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Grab-Timestamp", EX(picture->grab_ts));
|
ADD_TIME_HEADER("X-UStreamer-Grab-Timestamp", EX(frame->grab_ts));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Encode-Begin-Timestamp", EX(picture->encode_begin_ts));
|
ADD_TIME_HEADER("X-UStreamer-Encode-Begin-Timestamp", EX(frame->encode_begin_ts));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Encode-End-Timestamp", EX(picture->encode_end_ts));
|
ADD_TIME_HEADER("X-UStreamer-Encode-End-Timestamp", EX(frame->encode_end_ts));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Expose-Begin-Timestamp", EX(expose_begin_ts));
|
ADD_TIME_HEADER("X-UStreamer-Expose-Begin-Timestamp", EX(expose_begin_ts));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Expose-Cmp-Timestamp", EX(expose_cmp_ts));
|
ADD_TIME_HEADER("X-UStreamer-Expose-Cmp-Timestamp", EX(expose_cmp_ts));
|
||||||
ADD_TIME_HEADER("X-UStreamer-Expose-End-Timestamp", EX(expose_end_ts));
|
ADD_TIME_HEADER("X-UStreamer-Expose-End-Timestamp", EX(expose_end_ts));
|
||||||
@@ -645,7 +645,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
|||||||
"Content-Length: %zu" RN
|
"Content-Length: %zu" RN
|
||||||
"X-Timestamp: %.06Lf" RN
|
"X-Timestamp: %.06Lf" RN
|
||||||
"%s",
|
"%s",
|
||||||
EX(picture->used),
|
EX(frame->used),
|
||||||
get_now_real(),
|
get_now_real(),
|
||||||
(client->extra_headers ? "" : RN)
|
(client->extra_headers ? "" : RN)
|
||||||
));
|
));
|
||||||
@@ -666,12 +666,12 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
|||||||
RN,
|
RN,
|
||||||
bool_to_string(EX(online)),
|
bool_to_string(EX(online)),
|
||||||
EX(dropped),
|
EX(dropped),
|
||||||
EX(picture->width),
|
EX(frame->width),
|
||||||
EX(picture->height),
|
EX(frame->height),
|
||||||
client->fps,
|
client->fps,
|
||||||
EX(picture->grab_ts),
|
EX(frame->grab_ts),
|
||||||
EX(picture->encode_begin_ts),
|
EX(frame->encode_begin_ts),
|
||||||
EX(picture->encode_end_ts),
|
EX(frame->encode_end_ts),
|
||||||
EX(expose_begin_ts),
|
EX(expose_begin_ts),
|
||||||
EX(expose_cmp_ts),
|
EX(expose_cmp_ts),
|
||||||
EX(expose_end_ts),
|
EX(expose_end_ts),
|
||||||
@@ -680,7 +680,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!evbuffer_add(buf, (void *)EX(picture->data), EX(picture->used)));
|
assert(!evbuffer_add(buf, (void *)EX(frame->data), EX(frame->used)));
|
||||||
assert(evbuffer_add_printf(buf, RN "--" BOUNDARY RN));
|
assert(evbuffer_add_printf(buf, RN "--" BOUNDARY RN));
|
||||||
|
|
||||||
if (client->advance_headers) {
|
if (client->advance_headers) {
|
||||||
@@ -744,7 +744,7 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
|
|||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool picture_updated) {
|
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool frame_updated) {
|
||||||
struct evhttp_connection *conn;
|
struct evhttp_connection *conn;
|
||||||
struct bufferevent *buf_event;
|
struct bufferevent *buf_event;
|
||||||
long long now;
|
long long now;
|
||||||
@@ -765,16 +765,16 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
|||||||
&& client->dual_final_frames
|
&& client->dual_final_frames
|
||||||
&& stream_updated
|
&& stream_updated
|
||||||
&& client->updated_prev
|
&& client->updated_prev
|
||||||
&& !picture_updated
|
&& !frame_updated
|
||||||
);
|
);
|
||||||
|
|
||||||
if (dual_update || picture_updated || client->need_first_frame) {
|
if (dual_update || frame_updated || client->need_first_frame) {
|
||||||
buf_event = evhttp_connection_get_bufferevent(conn);
|
buf_event = evhttp_connection_get_bufferevent(conn);
|
||||||
bufferevent_setcb(buf_event, NULL, _http_callback_stream_write, _http_callback_stream_error, (void *)client);
|
bufferevent_setcb(buf_event, NULL, _http_callback_stream_write, _http_callback_stream_error, (void *)client);
|
||||||
bufferevent_enable(buf_event, EV_READ|EV_WRITE);
|
bufferevent_enable(buf_event, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
client->need_first_frame = false;
|
client->need_first_frame = false;
|
||||||
client->updated_prev = (picture_updated || client->need_first_frame); // Игнорировать dual
|
client->updated_prev = (frame_updated || client->need_first_frame); // Игнорировать dual
|
||||||
queued = true;
|
queued = true;
|
||||||
} else if (stream_updated) { // Для dual
|
} else if (stream_updated) { // Для dual
|
||||||
client->updated_prev = false;
|
client->updated_prev = false;
|
||||||
@@ -802,7 +802,7 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
|||||||
static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_server) {
|
static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_server) {
|
||||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||||
bool stream_updated = false;
|
bool stream_updated = false;
|
||||||
bool picture_updated = false;
|
bool frame_updated = false;
|
||||||
|
|
||||||
# define UNLOCK_STREAM { \
|
# define UNLOCK_STREAM { \
|
||||||
atomic_store(&STREAM(video->updated), false); \
|
atomic_store(&STREAM(video->updated), false); \
|
||||||
@@ -813,35 +813,35 @@ static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_serv
|
|||||||
LOG_DEBUG("Refreshing HTTP exposed ...");
|
LOG_DEBUG("Refreshing HTTP exposed ...");
|
||||||
A_MUTEX_LOCK(&STREAM(video->mutex));
|
A_MUTEX_LOCK(&STREAM(video->mutex));
|
||||||
if (STREAM(video->online)) {
|
if (STREAM(video->online)) {
|
||||||
picture_updated = _expose_new_picture_unsafe(server);
|
frame_updated = _expose_new_picture_unsafe(server);
|
||||||
UNLOCK_STREAM;
|
UNLOCK_STREAM;
|
||||||
} else {
|
} else {
|
||||||
UNLOCK_STREAM;
|
UNLOCK_STREAM;
|
||||||
picture_updated = _expose_blank_picture(server);
|
frame_updated = _expose_blank_picture(server);
|
||||||
}
|
}
|
||||||
stream_updated = true;
|
stream_updated = true;
|
||||||
} else if (!EX(online)) {
|
} else if (!EX(online)) {
|
||||||
LOG_DEBUG("Refreshing HTTP exposed (BLANK) ...");
|
LOG_DEBUG("Refreshing HTTP exposed (BLANK) ...");
|
||||||
picture_updated = _expose_blank_picture(server);
|
frame_updated = _expose_blank_picture(server);
|
||||||
stream_updated = true;
|
stream_updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
# undef UNLOCK_STREAM
|
# undef UNLOCK_STREAM
|
||||||
|
|
||||||
_http_queue_send_stream(server, stream_updated, picture_updated);
|
_http_queue_send_stream(server, stream_updated, frame_updated);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
picture_updated
|
frame_updated
|
||||||
&& server->notify_parent
|
&& server->notify_parent
|
||||||
&& (
|
&& (
|
||||||
EX(notify_last_online) != EX(online)
|
EX(notify_last_online) != EX(online)
|
||||||
|| EX(notify_last_width) != EX(picture->width)
|
|| EX(notify_last_width) != EX(frame->width)
|
||||||
|| EX(notify_last_height) != EX(picture->height)
|
|| EX(notify_last_height) != EX(frame->height)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
EX(notify_last_online) = EX(online);
|
EX(notify_last_online) = EX(online);
|
||||||
EX(notify_last_width) = EX(picture->width);
|
EX(notify_last_width) = EX(frame->width);
|
||||||
EX(notify_last_height) = EX(picture->height);
|
EX(notify_last_height) = EX(frame->height);
|
||||||
process_notify_parent();
|
process_notify_parent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -854,7 +854,7 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
|
|||||||
if (
|
if (
|
||||||
EX(online)
|
EX(online)
|
||||||
&& EX(dropped) < server->drop_same_frames
|
&& EX(dropped) < server->drop_same_frames
|
||||||
&& picture_compare(EX(picture), STREAM(video->picture))
|
&& frame_compare(EX(frame), STREAM(video->frame))
|
||||||
) {
|
) {
|
||||||
EX(expose_cmp_ts) = get_now_monotonic();
|
EX(expose_cmp_ts) = get_now_monotonic();
|
||||||
EX(expose_end_ts) = EX(expose_cmp_ts);
|
EX(expose_end_ts) = EX(expose_cmp_ts);
|
||||||
@@ -869,7 +869,7 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
picture_copy(STREAM(video->picture), EX(picture));
|
frame_copy(STREAM(video->frame), EX(frame));
|
||||||
|
|
||||||
EX(online) = true;
|
EX(online) = true;
|
||||||
EX(dropped) = 0;
|
EX(dropped) = 0;
|
||||||
@@ -886,11 +886,11 @@ static bool _expose_blank_picture(struct http_server_t *server) {
|
|||||||
EX(expose_begin_ts) = get_now_monotonic();
|
EX(expose_begin_ts) = get_now_monotonic();
|
||||||
EX(expose_cmp_ts) = EX(expose_begin_ts);
|
EX(expose_cmp_ts) = EX(expose_begin_ts);
|
||||||
|
|
||||||
# define EXPOSE_BLANK picture_copy(RUN(blank), EX(picture))
|
# define EXPOSE_BLANK frame_copy(RUN(blank), EX(frame))
|
||||||
|
|
||||||
if (EX(online)) { // Если переходим из online в offline
|
if (EX(online)) { // Если переходим из online в offline
|
||||||
if (server->last_as_blank < 0) { // Если last_as_blank выключено, просто покажем картинку
|
if (server->last_as_blank < 0) { // Если last_as_blank выключено, просто покажем картинку
|
||||||
LOG_INFO("HTTP: Changed picture to BLANK");
|
LOG_INFO("HTTP: Changed frame to BLANK");
|
||||||
EXPOSE_BLANK;
|
EXPOSE_BLANK;
|
||||||
} else if (server->last_as_blank > 0) { // Если нужен таймер - запустим
|
} else if (server->last_as_blank > 0) { // Если нужен таймер - запустим
|
||||||
LOG_INFO("HTTP: Freezing last alive frame for %d seconds", server->last_as_blank);
|
LOG_INFO("HTTP: Freezing last alive frame for %d seconds", server->last_as_blank);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include <event2/http.h>
|
#include <event2/http.h>
|
||||||
#include <event2/util.h>
|
#include <event2/util.h>
|
||||||
|
|
||||||
#include "../picture.h"
|
#include "../frame.h"
|
||||||
#include "../stream.h"
|
#include "../stream.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ struct stream_client_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct exposed_t {
|
struct exposed_t {
|
||||||
struct picture_t *picture;
|
struct frame_t *frame;
|
||||||
unsigned captured_fps;
|
unsigned captured_fps;
|
||||||
unsigned queued_fps;
|
unsigned queued_fps;
|
||||||
bool online;
|
bool online;
|
||||||
@@ -81,7 +81,7 @@ struct http_server_runtime_t {
|
|||||||
struct exposed_t *exposed;
|
struct exposed_t *exposed;
|
||||||
struct stream_client_t *stream_clients;
|
struct stream_client_t *stream_clients;
|
||||||
unsigned stream_clients_count;
|
unsigned stream_clients_count;
|
||||||
struct picture_t *blank;
|
struct frame_t *blank;
|
||||||
unsigned drop_same_frames_blank;
|
unsigned drop_same_frames_blank;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct _worker_t {
|
|||||||
atomic_bool *workers_stop;
|
atomic_bool *workers_stop;
|
||||||
|
|
||||||
long double last_comp_time;
|
long double last_comp_time;
|
||||||
struct picture_t *picture;
|
struct frame_t *frame;
|
||||||
|
|
||||||
pthread_mutex_t has_job_mutex;
|
pthread_mutex_t has_job_mutex;
|
||||||
unsigned buf_index;
|
unsigned buf_index;
|
||||||
@@ -70,7 +70,7 @@ struct _workers_pool_t {
|
|||||||
|
|
||||||
static struct _workers_pool_t *_stream_init_loop(struct stream_t *stream);
|
static struct _workers_pool_t *_stream_init_loop(struct stream_t *stream);
|
||||||
static struct _workers_pool_t *_stream_init_one(struct stream_t *stream);
|
static struct _workers_pool_t *_stream_init_one(struct stream_t *stream);
|
||||||
static void _stream_expose_picture(struct stream_t *stream, struct picture_t *picture, unsigned captured_fps);
|
static void _stream_expose_picture(struct stream_t *stream, struct frame_t *frame, unsigned captured_fps);
|
||||||
|
|
||||||
static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream);
|
static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream);
|
||||||
static void _workers_pool_destroy(struct _workers_pool_t *pool);
|
static void _workers_pool_destroy(struct _workers_pool_t *pool);
|
||||||
@@ -92,7 +92,7 @@ struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder) {
|
|||||||
atomic_init(&proc->slowdown, false);
|
atomic_init(&proc->slowdown, false);
|
||||||
|
|
||||||
A_CALLOC(video, 1);
|
A_CALLOC(video, 1);
|
||||||
video->picture = picture_init();
|
video->frame = frame_init();
|
||||||
atomic_init(&video->updated, false);
|
atomic_init(&video->updated, false);
|
||||||
A_MUTEX_INIT(&video->mutex);
|
A_MUTEX_INIT(&video->mutex);
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder) {
|
|||||||
|
|
||||||
void stream_destroy(struct stream_t *stream) {
|
void stream_destroy(struct stream_t *stream) {
|
||||||
A_MUTEX_DESTROY(&stream->video->mutex);
|
A_MUTEX_DESTROY(&stream->video->mutex);
|
||||||
picture_destroy(stream->video->picture);
|
frame_destroy(stream->video->frame);
|
||||||
free(stream->video);
|
free(stream->video);
|
||||||
free(stream->proc);
|
free(stream->proc);
|
||||||
free(stream);
|
free(stream);
|
||||||
@@ -140,8 +140,8 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
|
|
||||||
LOG_INFO("Capturing ...");
|
LOG_INFO("Capturing ...");
|
||||||
|
|
||||||
LOG_DEBUG("Pre-allocating memory for stream picture ...");
|
LOG_DEBUG("Pre-allocating memory for stream frame ...");
|
||||||
picture_realloc_data(stream->video->picture, picture_get_generous_size(DEV(run->width), DEV(run->height)));
|
frame_realloc_data(stream->video->frame, frame_get_generous_size(DEV(run->width), DEV(run->height)));
|
||||||
|
|
||||||
while (!atomic_load(&stream->proc->stop)) {
|
while (!atomic_load(&stream->proc->stop)) {
|
||||||
struct _worker_t *ready_wr;
|
struct _worker_t *ready_wr;
|
||||||
@@ -153,10 +153,10 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
|
|
||||||
if (!ready_wr->job_failed) {
|
if (!ready_wr->job_failed) {
|
||||||
if (ready_wr->job_timely) {
|
if (ready_wr->job_timely) {
|
||||||
_stream_expose_picture(stream, ready_wr->picture, captured_fps);
|
_stream_expose_picture(stream, ready_wr->frame, captured_fps);
|
||||||
LOG_PERF("##### Encoded picture exposed; worker=%u", ready_wr->number);
|
LOG_PERF("##### Encoded frame exposed; worker=%u", ready_wr->number);
|
||||||
} else {
|
} else {
|
||||||
LOG_PERF("----- Encoded picture dropped; worker=%u", ready_wr->number);
|
LOG_PERF("----- Encoded frame dropped; worker=%u", ready_wr->number);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -333,10 +333,10 @@ static struct _workers_pool_t *_stream_init_one(struct stream_t *stream) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _stream_expose_picture(struct stream_t *stream, struct picture_t *picture, unsigned captured_fps) {
|
static void _stream_expose_picture(struct stream_t *stream, struct frame_t *frame, unsigned captured_fps) {
|
||||||
A_MUTEX_LOCK(&stream->video->mutex);
|
A_MUTEX_LOCK(&stream->video->mutex);
|
||||||
|
|
||||||
picture_copy(picture, stream->video->picture);
|
frame_copy(frame, stream->video->frame);
|
||||||
|
|
||||||
stream->video->online = true;
|
stream->video->online = true;
|
||||||
stream->video->captured_fps = captured_fps;
|
stream->video->captured_fps = captured_fps;
|
||||||
@@ -350,7 +350,7 @@ static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream) {
|
|||||||
# define RUN(_next) stream->dev->run->_next
|
# define RUN(_next) stream->dev->run->_next
|
||||||
|
|
||||||
struct _workers_pool_t *pool;
|
struct _workers_pool_t *pool;
|
||||||
size_t picture_size = picture_get_generous_size(RUN(width), RUN(height));
|
size_t frame_size = frame_get_generous_size(RUN(width), RUN(height));
|
||||||
|
|
||||||
LOG_INFO("Creating pool with %u workers ...", stream->encoder->run->n_workers);
|
LOG_INFO("Creating pool with %u workers ...", stream->encoder->run->n_workers);
|
||||||
|
|
||||||
@@ -374,8 +374,8 @@ static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream) {
|
|||||||
for (unsigned number = 0; number < pool->n_workers; ++number) {
|
for (unsigned number = 0; number < pool->n_workers; ++number) {
|
||||||
# define WR(_next) pool->workers[number]._next
|
# define WR(_next) pool->workers[number]._next
|
||||||
|
|
||||||
WR(picture) = picture_init();
|
WR(frame) = frame_init();
|
||||||
picture_realloc_data(WR(picture), picture_size);
|
frame_realloc_data(WR(frame), frame_size);
|
||||||
|
|
||||||
A_MUTEX_INIT(&WR(has_job_mutex));
|
A_MUTEX_INIT(&WR(has_job_mutex));
|
||||||
atomic_init(&WR(has_job), false);
|
atomic_init(&WR(has_job), false);
|
||||||
@@ -416,7 +416,7 @@ static void _workers_pool_destroy(struct _workers_pool_t *pool) {
|
|||||||
A_MUTEX_DESTROY(&WR(has_job_mutex));
|
A_MUTEX_DESTROY(&WR(has_job_mutex));
|
||||||
A_COND_DESTROY(&WR(has_job_cond));
|
A_COND_DESTROY(&WR(has_job_cond));
|
||||||
|
|
||||||
picture_destroy(WR(picture));
|
frame_destroy(WR(frame));
|
||||||
|
|
||||||
# undef WR
|
# undef WR
|
||||||
}
|
}
|
||||||
@@ -442,7 +442,7 @@ static void *_worker_thread(void *v_worker) {
|
|||||||
A_MUTEX_UNLOCK(&wr->has_job_mutex);
|
A_MUTEX_UNLOCK(&wr->has_job_mutex);
|
||||||
|
|
||||||
if (!atomic_load(wr->workers_stop)) {
|
if (!atomic_load(wr->workers_stop)) {
|
||||||
# define PIC(_next) wr->picture->_next
|
# define PIC(_next) wr->frame->_next
|
||||||
|
|
||||||
LOG_DEBUG("Worker %u compressing JPEG from buffer %u ...", wr->number, wr->buf_index);
|
LOG_DEBUG("Worker %u compressing JPEG from buffer %u ...", wr->number, wr->buf_index);
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ static void *_worker_thread(void *v_worker) {
|
|||||||
wr->stream->encoder,
|
wr->stream->encoder,
|
||||||
wr->number,
|
wr->number,
|
||||||
&wr->stream->dev->run->hw_buffers[wr->buf_index],
|
&wr->stream->dev->run->hw_buffers[wr->buf_index],
|
||||||
wr->picture
|
wr->frame
|
||||||
);
|
);
|
||||||
|
|
||||||
if (device_release_buffer(wr->stream->dev, wr->buf_index) == 0) {
|
if (device_release_buffer(wr->stream->dev, wr->buf_index) == 0) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "../common/threading.h"
|
#include "../common/threading.h"
|
||||||
#include "../common/logging.h"
|
#include "../common/logging.h"
|
||||||
|
|
||||||
#include "picture.h"
|
#include "frame.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
#ifdef WITH_RAWSINK
|
#ifdef WITH_RAWSINK
|
||||||
@@ -52,7 +52,7 @@ struct process_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct video_t {
|
struct video_t {
|
||||||
struct picture_t *picture;
|
struct frame_t *frame;
|
||||||
bool online;
|
bool online;
|
||||||
unsigned captured_fps;
|
unsigned captured_fps;
|
||||||
atomic_bool updated;
|
atomic_bool updated;
|
||||||
|
|||||||
Reference in New Issue
Block a user