mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
mp4 recording code from @LemonSkin
This commit is contained in:
48
uxplay.cpp
48
uxplay.cpp
@@ -67,6 +67,7 @@
|
||||
#include "lib/crypto.h"
|
||||
#include "renderers/video_renderer.h"
|
||||
#include "renderers/audio_renderer.h"
|
||||
#include "renderers/mux_renderer.h"
|
||||
#ifdef DBUS
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
@@ -197,6 +198,8 @@ static std::string ble_filename = "";
|
||||
static std::string rtp_pipeline = "";
|
||||
static std::string audio_rtp_pipeline = "";
|
||||
static GMainLoop *gmainloop = NULL;
|
||||
static bool mux_to_file = false;
|
||||
static std::string mux_filename = "recording";
|
||||
|
||||
//Support for D-Bus-based screensaver inhibition (org.freedesktop.ScreenSaver)
|
||||
static unsigned int scrsv;
|
||||
@@ -906,6 +909,8 @@ static void print_info (char *name) {
|
||||
printf("-n name Specify network name of the AirPlay server (UTF-8/ascii)\n");
|
||||
printf("-nh Do not add \"@hostname\" at the end of AirPlay server name\n");
|
||||
printf("-h265 Support h265 (4K) video (with h265 versions of h264 plugins)\n");
|
||||
printf("-mp4 [fn] Record (non-HLS)audio/video to mp4 file \"fn.[n].[format].mp4\"\n");
|
||||
printf(" n=1,2,.. format = H264/5, ALAC/AAC. Default fn=\"recording\"\n");
|
||||
printf("-hls [v] Support HTTP Live Streaming (HLS), Youtube app video only: \n");
|
||||
printf(" v = 2 or 3 (default 3) optionally selects video player version\n");
|
||||
printf("-lang xx HLS language preferences (\"fr:es:..\", overrides $LANGUAGE)\n");
|
||||
@@ -951,6 +956,7 @@ static void print_info (char *name) {
|
||||
printf("-vrtp pl Use rtph26[4,5]pay to send decoded video elsewhere: \"pl\"\n");
|
||||
printf(" is the remaining pipeline, starting with rtph26*pay options:\n");
|
||||
printf(" e.g. \"config-interval=1 ! udpsink host=127.0.0.1 port=5000\"\n");
|
||||
printf(" Writes output to \"fn.N.mp4\"\n");
|
||||
printf("-v4l2 Use Video4Linux2 for GPU hardware h264 decoding\n");
|
||||
printf("-bt709 Sometimes needed for Raspberry Pi models using Video4Linux2 \n");
|
||||
printf("-srgb Display \"Full range\" [0-255] color, not \"Limited Range\"[16-235]\n");
|
||||
@@ -985,6 +991,9 @@ static void print_info (char *name) {
|
||||
printf("-key [fn] Store private key in $HOME/.uxplay.pem (or in file \"fn\")\n");
|
||||
printf("-dacp [fn]Export client DACP information to file $HOME/.uxplay.dacp\n");
|
||||
printf(" (option to use file \"fn\" instead); used for client remote\n");
|
||||
printf("-ble [fn] For BluetoothLE beacon: write data to file ~/.uxplay.ble\n");
|
||||
printf(" optional: write to file \"fn\" (\"fn\" = \"off\" to cancel)\n");
|
||||
printf("-d [n] Enable debug logging; optional: n=1 to skip normal packet data\n");
|
||||
printf("-vdmp [n] Dump h264 video output to \"fn.h264\"; fn=\"videodump\",change\n");
|
||||
printf(" with \"-vdmp [n] filename\". If [n] is given, file fn.x.h264\n");
|
||||
printf(" x=1,2,.. opens whenever a new SPS/PPS NAL arrives, and <=n\n");
|
||||
@@ -993,9 +1002,6 @@ static void print_info (char *name) {
|
||||
printf(" =1,2,..; fn=\"audiodump\"; change with \"-admp [n] filename\".\n");
|
||||
printf(" x increases when audio format changes. If n is given, <= n\n");
|
||||
printf(" audio packets are dumped. \"aud\"= unknown format.\n");
|
||||
printf("-ble [fn] For BluetoothLE beacon: write data to file ~/.uxplay.ble\n");
|
||||
printf(" optional: write to file \"fn\" (\"fn\" = \"off\" to cancel)\n");
|
||||
printf("-d [n] Enable debug logging; optional: n=1 to skip normal packet data\n");
|
||||
printf("-v Displays version information\n");
|
||||
printf("-h Displays this help\n");
|
||||
printf("-rc fn Read startup options from file \"fn\" instead of ~/.uxplayrc, etc\n");
|
||||
@@ -1480,6 +1486,17 @@ static void parse_arguments (int argc, char *argv[]) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else if (arg == "-mp4"){
|
||||
mux_to_file = true;
|
||||
if (i < argc - 1 && *argv[i+1] != '-') {
|
||||
mux_filename.erase();
|
||||
mux_filename.append(argv[++i]);
|
||||
const char *fn = mux_filename.c_str();
|
||||
if (!file_has_write_access(fn)) {
|
||||
fprintf(stderr, "%s cannot be written to:\noption \"-mp4 <fn>\" must be to a file with write access\n", fn);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else if (arg == "-admp") {
|
||||
dump_audio = true;
|
||||
if (i < argc - 1 && *argv[i+1] != '-') {
|
||||
@@ -2117,6 +2134,9 @@ extern "C" void video_reset(void *cls, reset_type_t type) {
|
||||
|
||||
extern "C" int video_set_codec(void *cls, video_codec_t codec) {
|
||||
bool video_is_h265 = (codec == VIDEO_CODEC_H265);
|
||||
if (mux_to_file) {
|
||||
mux_renderer_choose_video_codec(video_is_h265);
|
||||
}
|
||||
if (!use_video) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2176,7 +2196,10 @@ extern "C" void conn_destroy (void *cls) {
|
||||
}
|
||||
if (dacpfile.length()) {
|
||||
remove (dacpfile.c_str());
|
||||
}
|
||||
}
|
||||
if (mux_to_file) {
|
||||
mux_renderer_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2233,6 +2256,9 @@ extern "C" void audio_process (void *cls, raop_ntp_t *ntp, audio_decode_struct *
|
||||
if (dump_audio) {
|
||||
dump_audio_to_file(data->data, data->data_len, (data->data)[0] & 0xf0);
|
||||
}
|
||||
if (mux_to_file) {
|
||||
mux_renderer_push_audio(data->data, data->data_len, data->ntp_time_remote);
|
||||
}
|
||||
if (use_audio) {
|
||||
if (!remote_clock_offset) {
|
||||
uint64_t local_time = (data->ntp_time_local ? data->ntp_time_local : get_local_time());
|
||||
@@ -2265,6 +2291,9 @@ extern "C" void video_process (void *cls, raop_ntp_t *ntp, video_decode_struct *
|
||||
if (dump_video) {
|
||||
dump_video_to_file(data->data, data->data_len);
|
||||
}
|
||||
if (mux_to_file) {
|
||||
mux_renderer_push_video(data->data, data->data_len, data->ntp_time_remote);
|
||||
}
|
||||
if (use_video) {
|
||||
if (!remote_clock_offset) {
|
||||
uint64_t local_time = (data->ntp_time_local ? data->ntp_time_local : get_local_time());
|
||||
@@ -2403,6 +2432,10 @@ extern "C" void audio_get_format (void *cls, unsigned char *ct, unsigned short *
|
||||
audio_renderer_start(ct);
|
||||
}
|
||||
|
||||
if (mux_to_file) {
|
||||
mux_renderer_choose_audio_codec(*ct);
|
||||
}
|
||||
|
||||
if (coverart_filename.length()) {
|
||||
write_coverart(coverart_filename.c_str(), (const void *) empty_image, sizeof(empty_image));
|
||||
}
|
||||
@@ -3069,6 +3102,10 @@ int main (int argc, char *argv[]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mux_to_file) {
|
||||
mux_renderer_init(render_logger, mux_filename.c_str(), use_audio, use_video);
|
||||
}
|
||||
|
||||
if (udp[0]) {
|
||||
LOGI("using network ports UDP %d %d %d TCP %d %d %d", udp[0], udp[1], udp[2], tcp[0], tcp[1], tcp[2]);
|
||||
}
|
||||
@@ -3169,6 +3206,9 @@ int main (int argc, char *argv[]) {
|
||||
raop_start_httpd(raop, &port);
|
||||
raop_set_port(raop, port);
|
||||
}
|
||||
if (mux_to_file) {
|
||||
mux_renderer_stop();
|
||||
}
|
||||
goto reconnect;
|
||||
} else {
|
||||
LOGI("Stopping RAOP Server...");
|
||||
|
||||
Reference in New Issue
Block a user