Use sc_ prefix for recorder

This commit is contained in:
Romain Vimont 2022-02-02 19:37:28 +01:00
parent 0080d0b0ff
commit 4ee62abe1d
3 changed files with 67 additions and 64 deletions

View file

@ -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);
} }

View file

@ -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

View file

@ -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) {