Use sc_ prefix for recorder
This commit is contained in:
parent
0080d0b0ff
commit
4ee62abe1d
3 changed files with 67 additions and 64 deletions
|
@ -9,7 +9,7 @@
|
||||||
#include "util/str.h"
|
#include "util/str.h"
|
||||||
|
|
||||||
/** Downcast packet_sink to recorder */
|
/** Downcast packet_sink to recorder */
|
||||||
#define DOWNCAST(SINK) container_of(SINK, struct recorder, packet_sink)
|
#define DOWNCAST(SINK) container_of(SINK, struct sc_recorder, packet_sink)
|
||||||
|
|
||||||
static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
|
static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
|
||||||
|
|
||||||
|
@ -30,9 +30,9 @@ find_muxer(const char *name) {
|
||||||
return oformat;
|
return oformat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct record_packet *
|
static struct sc_record_packet *
|
||||||
record_packet_new(const AVPacket *packet) {
|
sc_record_packet_new(const AVPacket *packet) {
|
||||||
struct record_packet *rec = malloc(sizeof(*rec));
|
struct sc_record_packet *rec = malloc(sizeof(*rec));
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
LOG_OOM();
|
LOG_OOM();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -54,22 +54,22 @@ record_packet_new(const AVPacket *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
record_packet_delete(struct record_packet *rec) {
|
sc_record_packet_delete(struct sc_record_packet *rec) {
|
||||||
av_packet_free(&rec->packet);
|
av_packet_free(&rec->packet);
|
||||||
free(rec);
|
free(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recorder_queue_clear(struct recorder_queue *queue) {
|
sc_recorder_queue_clear(struct sc_recorder_queue *queue) {
|
||||||
while (!sc_queue_is_empty(queue)) {
|
while (!sc_queue_is_empty(queue)) {
|
||||||
struct record_packet *rec;
|
struct sc_record_packet *rec;
|
||||||
sc_queue_take(queue, next, &rec);
|
sc_queue_take(queue, next, &rec);
|
||||||
record_packet_delete(rec);
|
sc_record_packet_delete(rec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
recorder_get_format_name(enum sc_record_format format) {
|
sc_recorder_get_format_name(enum sc_record_format format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case SC_RECORD_FORMAT_MP4: return "mp4";
|
case SC_RECORD_FORMAT_MP4: return "mp4";
|
||||||
case SC_RECORD_FORMAT_MKV: return "matroska";
|
case SC_RECORD_FORMAT_MKV: return "matroska";
|
||||||
|
@ -78,7 +78,7 @@ recorder_get_format_name(enum sc_record_format format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_write_header(struct recorder *recorder, const AVPacket *packet) {
|
sc_recorder_write_header(struct sc_recorder *recorder, const AVPacket *packet) {
|
||||||
AVStream *ostream = recorder->ctx->streams[0];
|
AVStream *ostream = recorder->ctx->streams[0];
|
||||||
|
|
||||||
uint8_t *extradata = av_malloc(packet->size * sizeof(uint8_t));
|
uint8_t *extradata = av_malloc(packet->size * sizeof(uint8_t));
|
||||||
|
@ -103,19 +103,19 @@ recorder_write_header(struct recorder *recorder, const AVPacket *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recorder_rescale_packet(struct recorder *recorder, AVPacket *packet) {
|
sc_recorder_rescale_packet(struct sc_recorder *recorder, AVPacket *packet) {
|
||||||
AVStream *ostream = recorder->ctx->streams[0];
|
AVStream *ostream = recorder->ctx->streams[0];
|
||||||
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base);
|
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_write(struct recorder *recorder, AVPacket *packet) {
|
sc_recorder_write(struct sc_recorder *recorder, AVPacket *packet) {
|
||||||
if (!recorder->header_written) {
|
if (!recorder->header_written) {
|
||||||
if (packet->pts != AV_NOPTS_VALUE) {
|
if (packet->pts != AV_NOPTS_VALUE) {
|
||||||
LOGE("The first packet is not a config packet");
|
LOGE("The first packet is not a config packet");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ok = recorder_write_header(recorder, packet);
|
bool ok = sc_recorder_write_header(recorder, packet);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -128,13 +128,13 @@ recorder_write(struct recorder *recorder, AVPacket *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder_rescale_packet(recorder, packet);
|
sc_recorder_rescale_packet(recorder, packet);
|
||||||
return av_write_frame(recorder->ctx, packet) >= 0;
|
return av_write_frame(recorder->ctx, packet) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_recorder(void *data) {
|
run_recorder(void *data) {
|
||||||
struct recorder *recorder = data;
|
struct sc_recorder *recorder = data;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
|
@ -148,29 +148,29 @@ run_recorder(void *data) {
|
||||||
|
|
||||||
if (recorder->stopped && sc_queue_is_empty(&recorder->queue)) {
|
if (recorder->stopped && sc_queue_is_empty(&recorder->queue)) {
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
struct record_packet *last = recorder->previous;
|
struct sc_record_packet *last = recorder->previous;
|
||||||
if (last) {
|
if (last) {
|
||||||
// assign an arbitrary duration to the last packet
|
// assign an arbitrary duration to the last packet
|
||||||
last->packet->duration = 100000;
|
last->packet->duration = 100000;
|
||||||
bool ok = recorder_write(recorder, last->packet);
|
bool ok = sc_recorder_write(recorder, last->packet);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// failing to write the last frame is not very serious, no
|
// failing to write the last frame is not very serious, no
|
||||||
// future frame may depend on it, so the resulting file
|
// future frame may depend on it, so the resulting file
|
||||||
// will still be valid
|
// will still be valid
|
||||||
LOGW("Could not record last packet");
|
LOGW("Could not record last packet");
|
||||||
}
|
}
|
||||||
record_packet_delete(last);
|
sc_record_packet_delete(last);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct record_packet *rec;
|
struct sc_record_packet *rec;
|
||||||
sc_queue_take(&recorder->queue, next, &rec);
|
sc_queue_take(&recorder->queue, next, &rec);
|
||||||
|
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
|
|
||||||
// recorder->previous is only written from this thread, no need to lock
|
// recorder->previous is only written from this thread, no need to lock
|
||||||
struct record_packet *previous = recorder->previous;
|
struct sc_record_packet *previous = recorder->previous;
|
||||||
recorder->previous = rec;
|
recorder->previous = rec;
|
||||||
|
|
||||||
if (!previous) {
|
if (!previous) {
|
||||||
|
@ -186,15 +186,15 @@ run_recorder(void *data) {
|
||||||
rec->packet->pts - previous->packet->pts;
|
rec->packet->pts - previous->packet->pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = recorder_write(recorder, previous->packet);
|
bool ok = sc_recorder_write(recorder, previous->packet);
|
||||||
record_packet_delete(previous);
|
sc_record_packet_delete(previous);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGE("Could not record packet");
|
LOGE("Could not record packet");
|
||||||
|
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
recorder->failed = true;
|
recorder->failed = true;
|
||||||
// discard pending packets
|
// discard pending packets
|
||||||
recorder_queue_clear(&recorder->queue);
|
sc_recorder_queue_clear(&recorder->queue);
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ run_recorder(void *data) {
|
||||||
if (recorder->failed) {
|
if (recorder->failed) {
|
||||||
LOGE("Recording failed to %s", recorder->filename);
|
LOGE("Recording failed to %s", recorder->filename);
|
||||||
} else {
|
} else {
|
||||||
const char *format_name = recorder_get_format_name(recorder->format);
|
const char *format_name = sc_recorder_get_format_name(recorder->format);
|
||||||
LOGI("Recording complete to %s file: %s", format_name,
|
LOGI("Recording complete to %s file: %s", format_name,
|
||||||
recorder->filename);
|
recorder->filename);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ run_recorder(void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_open(struct recorder *recorder, const AVCodec *input_codec) {
|
sc_recorder_open(struct sc_recorder *recorder, const AVCodec *input_codec) {
|
||||||
bool ok = sc_mutex_init(&recorder->mutex);
|
bool ok = sc_mutex_init(&recorder->mutex);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -244,7 +244,7 @@ recorder_open(struct recorder *recorder, const AVCodec *input_codec) {
|
||||||
recorder->header_written = false;
|
recorder->header_written = false;
|
||||||
recorder->previous = NULL;
|
recorder->previous = NULL;
|
||||||
|
|
||||||
const char *format_name = recorder_get_format_name(recorder->format);
|
const char *format_name = sc_recorder_get_format_name(recorder->format);
|
||||||
assert(format_name);
|
assert(format_name);
|
||||||
const AVOutputFormat *format = find_muxer(format_name);
|
const AVOutputFormat *format = find_muxer(format_name);
|
||||||
if (!format) {
|
if (!format) {
|
||||||
|
@ -311,7 +311,7 @@ error_mutex_destroy:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recorder_close(struct recorder *recorder) {
|
sc_recorder_close(struct sc_recorder *recorder) {
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
recorder->stopped = true;
|
recorder->stopped = true;
|
||||||
sc_cond_signal(&recorder->queue_cond);
|
sc_cond_signal(&recorder->queue_cond);
|
||||||
|
@ -326,7 +326,7 @@ recorder_close(struct recorder *recorder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_push(struct recorder *recorder, const AVPacket *packet) {
|
sc_recorder_push(struct sc_recorder *recorder, const AVPacket *packet) {
|
||||||
sc_mutex_lock(&recorder->mutex);
|
sc_mutex_lock(&recorder->mutex);
|
||||||
assert(!recorder->stopped);
|
assert(!recorder->stopped);
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ recorder_push(struct recorder *recorder, const AVPacket *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct record_packet *rec = record_packet_new(packet);
|
struct sc_record_packet *rec = sc_record_packet_new(packet);
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
LOG_OOM();
|
LOG_OOM();
|
||||||
sc_mutex_unlock(&recorder->mutex);
|
sc_mutex_unlock(&recorder->mutex);
|
||||||
|
@ -351,28 +351,30 @@ recorder_push(struct recorder *recorder, const AVPacket *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_packet_sink_open(struct sc_packet_sink *sink, const AVCodec *codec) {
|
sc_recorder_packet_sink_open(struct sc_packet_sink *sink,
|
||||||
struct recorder *recorder = DOWNCAST(sink);
|
const AVCodec *codec) {
|
||||||
return recorder_open(recorder, codec);
|
struct sc_recorder *recorder = DOWNCAST(sink);
|
||||||
|
return sc_recorder_open(recorder, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recorder_packet_sink_close(struct sc_packet_sink *sink) {
|
sc_recorder_packet_sink_close(struct sc_packet_sink *sink) {
|
||||||
struct recorder *recorder = DOWNCAST(sink);
|
struct sc_recorder *recorder = DOWNCAST(sink);
|
||||||
recorder_close(recorder);
|
sc_recorder_close(recorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
recorder_packet_sink_push(struct sc_packet_sink *sink, const AVPacket *packet) {
|
sc_recorder_packet_sink_push(struct sc_packet_sink *sink,
|
||||||
struct recorder *recorder = DOWNCAST(sink);
|
const AVPacket *packet) {
|
||||||
return recorder_push(recorder, packet);
|
struct sc_recorder *recorder = DOWNCAST(sink);
|
||||||
|
return sc_recorder_push(recorder, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
recorder_init(struct recorder *recorder,
|
sc_recorder_init(struct sc_recorder *recorder,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
enum sc_record_format format,
|
enum sc_record_format format,
|
||||||
struct sc_size declared_frame_size) {
|
struct sc_size declared_frame_size) {
|
||||||
recorder->filename = strdup(filename);
|
recorder->filename = strdup(filename);
|
||||||
if (!recorder->filename) {
|
if (!recorder->filename) {
|
||||||
LOG_OOM();
|
LOG_OOM();
|
||||||
|
@ -383,9 +385,9 @@ recorder_init(struct recorder *recorder,
|
||||||
recorder->declared_frame_size = declared_frame_size;
|
recorder->declared_frame_size = declared_frame_size;
|
||||||
|
|
||||||
static const struct sc_packet_sink_ops ops = {
|
static const struct sc_packet_sink_ops ops = {
|
||||||
.open = recorder_packet_sink_open,
|
.open = sc_recorder_packet_sink_open,
|
||||||
.close = recorder_packet_sink_close,
|
.close = sc_recorder_packet_sink_close,
|
||||||
.push = recorder_packet_sink_push,
|
.push = sc_recorder_packet_sink_push,
|
||||||
};
|
};
|
||||||
|
|
||||||
recorder->packet_sink.ops = &ops;
|
recorder->packet_sink.ops = &ops;
|
||||||
|
@ -394,6 +396,6 @@ recorder_init(struct recorder *recorder,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
recorder_destroy(struct recorder *recorder) {
|
sc_recorder_destroy(struct sc_recorder *recorder) {
|
||||||
free(recorder->filename);
|
free(recorder->filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef RECORDER_H
|
#ifndef SC_RECORDER_H
|
||||||
#define RECORDER_H
|
#define SC_RECORDER_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
@ -12,14 +12,14 @@
|
||||||
#include "util/queue.h"
|
#include "util/queue.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
|
|
||||||
struct record_packet {
|
struct sc_record_packet {
|
||||||
AVPacket *packet;
|
AVPacket *packet;
|
||||||
struct record_packet *next;
|
struct sc_record_packet *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct recorder_queue SC_QUEUE(struct record_packet);
|
struct sc_recorder_queue SC_QUEUE(struct sc_record_packet);
|
||||||
|
|
||||||
struct recorder {
|
struct sc_recorder {
|
||||||
struct sc_packet_sink packet_sink; // packet sink trait
|
struct sc_packet_sink packet_sink; // packet sink trait
|
||||||
|
|
||||||
char *filename;
|
char *filename;
|
||||||
|
@ -33,20 +33,21 @@ struct recorder {
|
||||||
sc_cond queue_cond;
|
sc_cond queue_cond;
|
||||||
bool stopped; // set on recorder_close()
|
bool stopped; // set on recorder_close()
|
||||||
bool failed; // set on packet write failure
|
bool failed; // set on packet write failure
|
||||||
struct recorder_queue queue;
|
struct sc_recorder_queue queue;
|
||||||
|
|
||||||
// we can write a packet only once we received the next one so that we can
|
// we can write a packet only once we received the next one so that we can
|
||||||
// set its duration (next_pts - current_pts)
|
// set its duration (next_pts - current_pts)
|
||||||
// "previous" is only accessed from the recorder thread, so it does not
|
// "previous" is only accessed from the recorder thread, so it does not
|
||||||
// need to be protected by the mutex
|
// need to be protected by the mutex
|
||||||
struct record_packet *previous;
|
struct sc_record_packet *previous;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
recorder_init(struct recorder *recorder, const char *filename,
|
sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
||||||
enum sc_record_format format, struct sc_size declared_frame_size);
|
enum sc_record_format format,
|
||||||
|
struct sc_size declared_frame_size);
|
||||||
|
|
||||||
void
|
void
|
||||||
recorder_destroy(struct recorder *recorder);
|
sc_recorder_destroy(struct sc_recorder *recorder);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct scrcpy {
|
||||||
struct sc_screen screen;
|
struct sc_screen screen;
|
||||||
struct stream stream;
|
struct stream stream;
|
||||||
struct sc_decoder decoder;
|
struct sc_decoder decoder;
|
||||||
struct recorder recorder;
|
struct sc_recorder recorder;
|
||||||
#ifdef HAVE_V4L2
|
#ifdef HAVE_V4L2
|
||||||
struct sc_v4l2_sink v4l2_sink;
|
struct sc_v4l2_sink v4l2_sink;
|
||||||
#endif
|
#endif
|
||||||
|
@ -381,12 +381,12 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
dec = &s->decoder;
|
dec = &s->decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct recorder *rec = NULL;
|
struct sc_recorder *rec = NULL;
|
||||||
if (options->record_filename) {
|
if (options->record_filename) {
|
||||||
if (!recorder_init(&s->recorder,
|
if (!sc_recorder_init(&s->recorder,
|
||||||
options->record_filename,
|
options->record_filename,
|
||||||
options->record_format,
|
options->record_format,
|
||||||
info->frame_size)) {
|
info->frame_size)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
rec = &s->recorder;
|
rec = &s->recorder;
|
||||||
|
@ -708,7 +708,7 @@ end:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recorder_initialized) {
|
if (recorder_initialized) {
|
||||||
recorder_destroy(&s->recorder);
|
sc_recorder_destroy(&s->recorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_pusher_initialized) {
|
if (file_pusher_initialized) {
|
||||||
|
|
Loading…
Reference in a new issue