mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-11 10:03:43 +00:00
refactoring
This commit is contained in:
@@ -186,7 +186,7 @@ void device_close(device_s *dev) {
|
|||||||
if (dev->io_method == V4L2_MEMORY_MMAP) {
|
if (dev->io_method == V4L2_MEMORY_MMAP) {
|
||||||
if (HW(raw.allocated) > 0 && HW(raw.data) != MAP_FAILED) {
|
if (HW(raw.allocated) > 0 && HW(raw.data) != MAP_FAILED) {
|
||||||
if (munmap(HW(raw.data), HW(raw.allocated)) < 0) {
|
if (munmap(HW(raw.data), HW(raw.allocated)) < 0) {
|
||||||
LOG_PERROR("Can't unmap device buffer index=%u", index);
|
LOG_PERROR("Can't unmap device buffer=%u", index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // V4L2_MEMORY_USERPTR
|
} else { // V4L2_MEMORY_USERPTR
|
||||||
@@ -222,9 +222,9 @@ int device_export_to_dma(device_s *dev) {
|
|||||||
exp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
exp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
exp.index = index;
|
exp.index = index;
|
||||||
|
|
||||||
LOG_DEBUG("Exporting device buffer index=%u to DMA ...", index);
|
LOG_DEBUG("Exporting device buffer=%u to DMA ...", index);
|
||||||
if (xioctl(RUN(fd), VIDIOC_EXPBUF, &exp) < 0) {
|
if (xioctl(RUN(fd), VIDIOC_EXPBUF, &exp) < 0) {
|
||||||
LOG_PERROR("Unable to export device buffer index=%u to DMA", index);
|
LOG_PERROR("Unable to export device buffer=%u to DMA", index);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
DMA_FD = exp.fd;
|
DMA_FD = exp.fd;
|
||||||
@@ -321,12 +321,10 @@ int device_grab_buffer(device_s *dev, hw_buffer_s **hw) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Grabbed new frame in device buffer: index=%u, bytesused=%u",
|
LOG_DEBUG("Grabbed new frame: buffer=%u, bytesused=%u", buf.index, buf.bytesused);
|
||||||
buf.index, buf.bytesused);
|
|
||||||
|
|
||||||
if (buf.index >= RUN(n_bufs)) {
|
if (buf.index >= RUN(n_bufs)) {
|
||||||
LOG_ERROR("V4L2 error: grabbed invalid device buffer: index=%u, n_bufs=%u",
|
LOG_ERROR("V4L2 error: grabbed invalid device buffer=%u, n_bufs=%u", buf.index, RUN(n_bufs));
|
||||||
buf.index, RUN(n_bufs));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,10 +334,11 @@ int device_grab_buffer(device_s *dev, hw_buffer_s **hw) {
|
|||||||
// For example a VGA (640x480) webcam frame 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.bytesused < dev->min_frame_size) {
|
if (buf.bytesused < dev->min_frame_size) {
|
||||||
LOG_DEBUG("Dropped too small frame sized %d bytes, assuming it was broken", buf.bytesused);
|
LOG_DEBUG("Dropped too small frame, assuming it was broken: buffer=%u, bytesused=%u",
|
||||||
LOG_DEBUG("Releasing device buffer index=%u (broken frame) ...", buf.index);
|
buf.index, buf.bytesused);
|
||||||
|
LOG_DEBUG("Releasing device buffer=%u (broken frame) ...", buf.index);
|
||||||
if (xioctl(RUN(fd), VIDIOC_QBUF, &buf) < 0) {
|
if (xioctl(RUN(fd), VIDIOC_QBUF, &buf) < 0) {
|
||||||
LOG_PERROR("Unable to release device buffer index=%u (broken frame)", buf.index);
|
LOG_PERROR("Unable to release device buffer=%u (broken frame)", buf.index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return -2;
|
return -2;
|
||||||
@@ -349,8 +348,7 @@ int device_grab_buffer(device_s *dev, hw_buffer_s **hw) {
|
|||||||
|
|
||||||
A_MUTEX_LOCK(&HW(grabbed_mutex));
|
A_MUTEX_LOCK(&HW(grabbed_mutex));
|
||||||
if (HW(grabbed)) {
|
if (HW(grabbed)) {
|
||||||
LOG_ERROR("V4L2 error: grabbed device buffer is already used: index=%u, bytesused=%u",
|
LOG_ERROR("V4L2 error: grabbed device buffer=%u is already used", buf.index);
|
||||||
buf.index, buf.bytesused);
|
|
||||||
A_MUTEX_UNLOCK(&HW(grabbed_mutex));
|
A_MUTEX_UNLOCK(&HW(grabbed_mutex));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -374,11 +372,11 @@ int device_grab_buffer(device_s *dev, hw_buffer_s **hw) {
|
|||||||
|
|
||||||
int device_release_buffer(device_s *dev, hw_buffer_s *hw) {
|
int device_release_buffer(device_s *dev, hw_buffer_s *hw) {
|
||||||
const unsigned index = hw->buf.index;
|
const unsigned index = hw->buf.index;
|
||||||
LOG_DEBUG("Releasing device buffer index=%u ...", index);
|
LOG_DEBUG("Releasing device buffer=%u ...", index);
|
||||||
|
|
||||||
A_MUTEX_LOCK(&hw->grabbed_mutex);
|
A_MUTEX_LOCK(&hw->grabbed_mutex);
|
||||||
if (xioctl(RUN(fd), VIDIOC_QBUF, &hw->buf) < 0) {
|
if (xioctl(RUN(fd), VIDIOC_QBUF, &hw->buf) < 0) {
|
||||||
LOG_PERROR("Unable to release device buffer index=%u", index);
|
LOG_PERROR("Unable to release device buffer=%u", index);
|
||||||
A_MUTEX_UNLOCK(&hw->grabbed_mutex);
|
A_MUTEX_UNLOCK(&hw->grabbed_mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -680,7 +678,7 @@ static int _device_open_io_method_mmap(device_s *dev) {
|
|||||||
buf.memory = V4L2_MEMORY_MMAP;
|
buf.memory = V4L2_MEMORY_MMAP;
|
||||||
buf.index = RUN(n_bufs);
|
buf.index = RUN(n_bufs);
|
||||||
|
|
||||||
LOG_DEBUG("Calling ioctl(VIDIOC_QUERYBUF) for device buffer index=%u ...", RUN(n_bufs));
|
LOG_DEBUG("Calling ioctl(VIDIOC_QUERYBUF) for device buffer=%u ...", RUN(n_bufs));
|
||||||
if (xioctl(RUN(fd), VIDIOC_QUERYBUF, &buf) < 0) {
|
if (xioctl(RUN(fd), VIDIOC_QUERYBUF, &buf) < 0) {
|
||||||
LOG_PERROR("Can't VIDIOC_QUERYBUF");
|
LOG_PERROR("Can't VIDIOC_QUERYBUF");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -692,7 +690,7 @@ static int _device_open_io_method_mmap(device_s *dev) {
|
|||||||
|
|
||||||
A_MUTEX_INIT(&HW(grabbed_mutex));
|
A_MUTEX_INIT(&HW(grabbed_mutex));
|
||||||
|
|
||||||
LOG_DEBUG("Mapping device buffer index=%u ...", RUN(n_bufs));
|
LOG_DEBUG("Mapping device buffer=%u ...", RUN(n_bufs));
|
||||||
if ((HW(raw.data) = mmap(
|
if ((HW(raw.data) = mmap(
|
||||||
NULL,
|
NULL,
|
||||||
buf.length,
|
buf.length,
|
||||||
@@ -701,7 +699,7 @@ static int _device_open_io_method_mmap(device_s *dev) {
|
|||||||
RUN(fd),
|
RUN(fd),
|
||||||
buf.m.offset
|
buf.m.offset
|
||||||
)) == MAP_FAILED) {
|
)) == MAP_FAILED) {
|
||||||
LOG_PERROR("Can't map device buffer index=%u", RUN(n_bufs));
|
LOG_PERROR("Can't map device buffer=%u", RUN(n_bufs));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
HW(raw.allocated) = buf.length;
|
HW(raw.allocated) = buf.length;
|
||||||
@@ -758,7 +756,7 @@ static int _device_open_queue_buffers(device_s *dev) {
|
|||||||
buf.length = RUN(hw_bufs)[index].raw.allocated;
|
buf.length = RUN(hw_bufs)[index].raw.allocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) for buffer index=%u ...", index);
|
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) for buffer=%u ...", index);
|
||||||
if (xioctl(RUN(fd), VIDIOC_QBUF, &buf) < 0) {
|
if (xioctl(RUN(fd), VIDIOC_QBUF, &buf) < 0) {
|
||||||
LOG_PERROR("Can't VIDIOC_QBUF");
|
LOG_PERROR("Can't VIDIOC_QBUF");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -202,26 +202,28 @@ static bool _worker_run_job(worker_s *wr) {
|
|||||||
|
|
||||||
# define ER(_next) job->enc->run->_next
|
# define ER(_next) job->enc->run->_next
|
||||||
|
|
||||||
LOG_DEBUG("Worker %s compressing JPEG from buffer index=%u ...", wr->name, job->hw->buf.index);
|
|
||||||
|
|
||||||
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
|
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
|
||||||
|
|
||||||
if (ER(type) == ENCODER_TYPE_CPU) {
|
if (ER(type) == ENCODER_TYPE_CPU) {
|
||||||
LOG_VERBOSE("Compressing buffer using CPU");
|
LOG_VERBOSE("Compressing JPEG using CPU: worker=%s, buffer=%u",
|
||||||
|
wr->name, job->hw->buf.index);
|
||||||
cpu_encoder_compress(src, dest, ER(quality));
|
cpu_encoder_compress(src, dest, 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 JPEG using HW (just copying): worker=%s, buffer=%u",
|
||||||
|
wr->name, job->hw->buf.index);
|
||||||
hw_encoder_compress(src, dest);
|
hw_encoder_compress(src, dest);
|
||||||
|
|
||||||
} else if (ER(type) == ENCODER_TYPE_M2M_VIDEO || ER(type) == ENCODER_TYPE_M2M_IMAGE) {
|
} else if (ER(type) == ENCODER_TYPE_M2M_VIDEO || ER(type) == ENCODER_TYPE_M2M_IMAGE) {
|
||||||
LOG_VERBOSE("Compressing buffer using M2M-%s", (ER(type) == ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"));
|
LOG_VERBOSE("Compressing JPEG using M2M-%s: worker=%s, buffer=%u",
|
||||||
|
(ER(type) == ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), wr->name, job->hw->buf.index);
|
||||||
if (m2m_encoder_compress(ER(m2ms[wr->number]), src, dest, false) < 0) {
|
if (m2m_encoder_compress(ER(m2ms[wr->number]), src, dest, false) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ER(type) == ENCODER_TYPE_NOOP) {
|
} else if (ER(type) == ENCODER_TYPE_NOOP) {
|
||||||
LOG_VERBOSE("Compressing buffer using NOOP (do nothing)");
|
LOG_VERBOSE("Compressing JPEG using NOOP (do nothing): worker=%s, buffer=%u",
|
||||||
|
wr->name, job->hw->buf.index);
|
||||||
usleep(5000); // Просто чтобы работала логика desired_fps
|
usleep(5000); // Просто чтобы работала логика desired_fps
|
||||||
dest->encode_end_ts = get_now_monotonic();
|
dest->encode_end_ts = get_now_monotonic();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ void m2m_encoder_destroy(m2m_encoder_s *enc) {
|
|||||||
#define RUN(_next) enc->run->_next
|
#define RUN(_next) enc->run->_next
|
||||||
|
|
||||||
int m2m_encoder_compress(m2m_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key) {
|
int m2m_encoder_compress(m2m_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key) {
|
||||||
|
frame_encoding_begin(src, dest, (enc->output_format == V4L2_PIX_FMT_MJPEG ? V4L2_PIX_FMT_JPEG : enc->output_format));
|
||||||
|
|
||||||
if (
|
if (
|
||||||
RUN(width) != src->width
|
RUN(width) != src->width
|
||||||
|| RUN(height) != src->height
|
|| RUN(height) != src->height
|
||||||
@@ -119,11 +121,6 @@ int m2m_encoder_compress(m2m_encoder_s *enc, const frame_s *src, frame_s *dest,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(RUN(ready));
|
|
||||||
assert(src->used > 0);
|
|
||||||
|
|
||||||
frame_encoding_begin(src, dest, (enc->output_format == V4L2_PIX_FMT_MJPEG ? V4L2_PIX_FMT_JPEG : enc->output_format));
|
|
||||||
|
|
||||||
force_key = (enc->output_format == V4L2_PIX_FMT_H264 && (force_key || RUN(last_online) != src->online));
|
force_key = (enc->output_format == V4L2_PIX_FMT_H264 && (force_key || RUN(last_online) != src->online));
|
||||||
|
|
||||||
if (_m2m_encoder_compress_raw(enc, src, dest, force_key) < 0) {
|
if (_m2m_encoder_compress_raw(enc, src, dest, force_key) < 0) {
|
||||||
@@ -324,10 +321,10 @@ static int _m2m_encoder_init_buffers(
|
|||||||
buf.length = 1;
|
buf.length = 1;
|
||||||
buf.m.planes = &plane;
|
buf.m.planes = &plane;
|
||||||
|
|
||||||
E_LOG_DEBUG("Querying %s buffer index=%u ...", name, *n_bufs_ptr);
|
E_LOG_DEBUG("Querying %s buffer=%u ...", name, *n_bufs_ptr);
|
||||||
E_XIOCTL(VIDIOC_QUERYBUF, &buf, "Can't query %s buffer index=%u", name, *n_bufs_ptr);
|
E_XIOCTL(VIDIOC_QUERYBUF, &buf, "Can't query %s buffer=%u", name, *n_bufs_ptr);
|
||||||
|
|
||||||
E_LOG_DEBUG("Mapping %s buffer index=%u ...", name, *n_bufs_ptr);
|
E_LOG_DEBUG("Mapping %s buffer=%u ...", name, *n_bufs_ptr);
|
||||||
if (((*bufs_ptr)[*n_bufs_ptr].data = mmap(
|
if (((*bufs_ptr)[*n_bufs_ptr].data = mmap(
|
||||||
NULL,
|
NULL,
|
||||||
plane.length,
|
plane.length,
|
||||||
@@ -336,13 +333,13 @@ static int _m2m_encoder_init_buffers(
|
|||||||
RUN(fd),
|
RUN(fd),
|
||||||
plane.m.mem_offset
|
plane.m.mem_offset
|
||||||
)) == MAP_FAILED) {
|
)) == MAP_FAILED) {
|
||||||
E_LOG_PERROR("Can't map %s buffer index=%u", name, *n_bufs_ptr);
|
E_LOG_PERROR("Can't map %s buffer=%u", name, *n_bufs_ptr);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
(*bufs_ptr)[*n_bufs_ptr].allocated = plane.length;
|
(*bufs_ptr)[*n_bufs_ptr].allocated = plane.length;
|
||||||
|
|
||||||
E_LOG_DEBUG("Queuing %s buffer index=%u ...", name, *n_bufs_ptr);
|
E_LOG_DEBUG("Queuing %s buffer=%u ...", name, *n_bufs_ptr);
|
||||||
E_XIOCTL(VIDIOC_QBUF, &buf, "Can't queue %s buffer index=%u", name, *n_bufs_ptr);
|
E_XIOCTL(VIDIOC_QBUF, &buf, "Can't queue %s buffer=%u", name, *n_bufs_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +369,7 @@ static void _m2m_encoder_cleanup(m2m_encoder_s *enc) {
|
|||||||
for (unsigned index = 0; index < RUN(n_##_target##_bufs); ++index) { \
|
for (unsigned index = 0; index < RUN(n_##_target##_bufs); ++index) { \
|
||||||
if (RUN(_target##_bufs[index].allocated) > 0 && RUN(_target##_bufs[index].data) != MAP_FAILED) { \
|
if (RUN(_target##_bufs[index].allocated) > 0 && RUN(_target##_bufs[index].data) != MAP_FAILED) { \
|
||||||
if (munmap(RUN(_target##_bufs[index].data), RUN(_target##_bufs[index].allocated)) < 0) { \
|
if (munmap(RUN(_target##_bufs[index].data), RUN(_target##_bufs[index].allocated)) < 0) { \
|
||||||
E_LOG_PERROR("Can't unmap %s buffer index=%u", #_name, index); \
|
E_LOG_PERROR("Can't unmap %s buffer=%u", #_name, index); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@@ -401,6 +398,8 @@ static void _m2m_encoder_cleanup(m2m_encoder_s *enc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key) {
|
static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key) {
|
||||||
|
assert(RUN(ready));
|
||||||
|
|
||||||
E_LOG_DEBUG("Compressing new frame; force_key=%d ...", force_key);
|
E_LOG_DEBUG("Compressing new frame; force_key=%d ...", force_key);
|
||||||
|
|
||||||
if (force_key) {
|
if (force_key) {
|
||||||
@@ -422,17 +421,17 @@ static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, fra
|
|||||||
input_buf.memory = V4L2_MEMORY_DMABUF;
|
input_buf.memory = V4L2_MEMORY_DMABUF;
|
||||||
input_buf.field = V4L2_FIELD_NONE;
|
input_buf.field = V4L2_FIELD_NONE;
|
||||||
input_plane.m.fd = src->dma_fd;
|
input_plane.m.fd = src->dma_fd;
|
||||||
E_LOG_DEBUG("Using INPUT-DMA buffer index=%u", input_buf.index);
|
E_LOG_DEBUG("Using INPUT-DMA buffer=%u", input_buf.index);
|
||||||
} else {
|
} else {
|
||||||
input_buf.memory = V4L2_MEMORY_MMAP;
|
input_buf.memory = V4L2_MEMORY_MMAP;
|
||||||
E_LOG_DEBUG("Grabbing INPUT buffer ...");
|
E_LOG_DEBUG("Grabbing INPUT buffer ...");
|
||||||
E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't grab INPUT buffer");
|
E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't grab INPUT buffer");
|
||||||
if (input_buf.index >= RUN(n_input_bufs)) {
|
if (input_buf.index >= RUN(n_input_bufs)) {
|
||||||
E_LOG_ERROR("V4L2 error: grabbed invalid INPUT buffer: index=%u, n_bufs=%u",
|
E_LOG_ERROR("V4L2 error: grabbed invalid INPUT: buffer=%u, n_bufs=%u",
|
||||||
input_buf.index, RUN(n_input_bufs));
|
input_buf.index, RUN(n_input_bufs));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
E_LOG_DEBUG("Grabbed INPUT buffer index=%u", input_buf.index);
|
E_LOG_DEBUG("Grabbed INPUT buffer=%u", input_buf.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t now = get_now_monotonic_u64();
|
uint64_t now = get_now_monotonic_u64();
|
||||||
@@ -468,8 +467,8 @@ static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, fra
|
|||||||
|
|
||||||
if (enc_poll.revents & POLLIN) {
|
if (enc_poll.revents & POLLIN) {
|
||||||
if (!input_released) {
|
if (!input_released) {
|
||||||
E_LOG_DEBUG("Releasing %s buffer index=%u ...", input_name, input_buf.index);
|
E_LOG_DEBUG("Releasing %s buffer=%u ...", input_name, input_buf.index);
|
||||||
E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't release %s buffer index=%u",
|
E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't release %s buffer=%u",
|
||||||
input_name, input_buf.index);
|
input_name, input_buf.index);
|
||||||
input_released = true;
|
input_released = true;
|
||||||
}
|
}
|
||||||
@@ -495,8 +494,8 @@ static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, fra
|
|||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
E_LOG_DEBUG("Releasing OUTPUT buffer index=%u ...", output_buf.index);
|
E_LOG_DEBUG("Releasing OUTPUT buffer=%u ...", output_buf.index);
|
||||||
E_XIOCTL(VIDIOC_QBUF, &output_buf, "Can't release OUTPUT buffer index=%u", output_buf.index);
|
E_XIOCTL(VIDIOC_QBUF, &output_buf, "Can't release OUTPUT buffer=%u", output_buf.index);
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ void stream_loop(stream_s *stream) {
|
|||||||
|
|
||||||
ready_job->hw = hw;
|
ready_job->hw = hw;
|
||||||
workers_pool_assign(pool, ready_wr);
|
workers_pool_assign(pool, ready_wr);
|
||||||
LOG_DEBUG("Assigned new frame in buffer %d to worker %s", buf_index, ready_wr->name);
|
LOG_DEBUG("Assigned new frame in buffer=%d to worker=%s", buf_index, ready_wr->name);
|
||||||
|
|
||||||
SINK_PUT(raw_sink, &hw->raw);
|
SINK_PUT(raw_sink, &hw->raw);
|
||||||
H264_PUT(&hw->raw, h264_force_key);
|
H264_PUT(&hw->raw, h264_force_key);
|
||||||
|
|||||||
Reference in New Issue
Block a user