2022-02-02 19:51:07 +00:00
|
|
|
#include "demuxer.h"
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2019-11-27 20:11:40 +00:00
|
|
|
#include <assert.h>
|
2023-03-12 07:54:42 +00:00
|
|
|
#include <libavutil/channel_layout.h>
|
2019-03-02 15:43:43 +00:00
|
|
|
#include <libavutil/time.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "decoder.h"
|
|
|
|
#include "events.h"
|
2023-02-10 21:52:40 +00:00
|
|
|
#include "packet_merger.h"
|
2019-03-02 15:43:43 +00:00
|
|
|
#include "recorder.h"
|
2022-08-03 13:13:16 +00:00
|
|
|
#include "util/binary.h"
|
2019-11-24 10:53:00 +00:00
|
|
|
#include "util/log.h"
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2022-02-11 20:34:58 +00:00
|
|
|
#define SC_PACKET_HEADER_SIZE 12
|
2022-02-11 18:31:01 +00:00
|
|
|
|
|
|
|
#define SC_PACKET_FLAG_CONFIG (UINT64_C(1) << 63)
|
2022-02-11 18:33:35 +00:00
|
|
|
#define SC_PACKET_FLAG_KEY_FRAME (UINT64_C(1) << 62)
|
2022-02-11 18:31:01 +00:00
|
|
|
|
2022-02-11 18:33:35 +00:00
|
|
|
#define SC_PACKET_PTS_MASK (SC_PACKET_FLAG_KEY_FRAME - 1)
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2023-02-03 11:35:37 +00:00
|
|
|
static enum AVCodecID
|
2023-02-10 17:48:20 +00:00
|
|
|
sc_demuxer_to_avcodec_id(uint32_t codec_id) {
|
2023-02-03 11:35:37 +00:00
|
|
|
#define SC_CODEC_ID_H264 UINT32_C(0x68323634) // "h264" in ASCII
|
2023-02-03 11:40:55 +00:00
|
|
|
#define SC_CODEC_ID_H265 UINT32_C(0x68323635) // "h265" in ASCII
|
2023-02-03 11:42:22 +00:00
|
|
|
#define SC_CODEC_ID_AV1 UINT32_C(0x00617631) // "av1" in ASCII
|
2023-02-06 09:33:47 +00:00
|
|
|
#define SC_CODEC_ID_OPUS UINT32_C(0x6f707573) // "opus" in ASCII
|
2023-11-07 12:09:47 +00:00
|
|
|
#define SC_CODEC_ID_AAC UINT32_C(0x00616163) // "aac" in ASCII
|
|
|
|
#define SC_CODEC_ID_FLAC UINT32_C(0x666c6163) // "flac" in ASCII
|
2023-03-03 20:19:37 +00:00
|
|
|
#define SC_CODEC_ID_RAW UINT32_C(0x00726177) // "raw" in ASCII
|
2023-02-03 11:35:37 +00:00
|
|
|
switch (codec_id) {
|
|
|
|
case SC_CODEC_ID_H264:
|
|
|
|
return AV_CODEC_ID_H264;
|
2023-02-03 11:40:55 +00:00
|
|
|
case SC_CODEC_ID_H265:
|
|
|
|
return AV_CODEC_ID_HEVC;
|
2023-02-03 11:42:22 +00:00
|
|
|
case SC_CODEC_ID_AV1:
|
2023-04-22 17:46:45 +00:00
|
|
|
#ifdef SCRCPY_LAVC_HAS_AV1
|
2023-02-03 11:42:22 +00:00
|
|
|
return AV_CODEC_ID_AV1;
|
2023-04-22 17:46:45 +00:00
|
|
|
#else
|
|
|
|
LOGE("AV1 not supported by this FFmpeg version");
|
|
|
|
return AV_CODEC_ID_NONE;
|
|
|
|
#endif
|
2023-02-06 09:33:47 +00:00
|
|
|
case SC_CODEC_ID_OPUS:
|
|
|
|
return AV_CODEC_ID_OPUS;
|
2023-02-18 18:30:36 +00:00
|
|
|
case SC_CODEC_ID_AAC:
|
|
|
|
return AV_CODEC_ID_AAC;
|
2023-11-07 12:09:47 +00:00
|
|
|
case SC_CODEC_ID_FLAC:
|
|
|
|
return AV_CODEC_ID_FLAC;
|
2023-03-03 20:19:37 +00:00
|
|
|
case SC_CODEC_ID_RAW:
|
|
|
|
return AV_CODEC_ID_PCM_S16LE;
|
2023-02-03 11:35:37 +00:00
|
|
|
default:
|
|
|
|
LOGE("Unknown codec id 0x%08" PRIx32, codec_id);
|
|
|
|
return AV_CODEC_ID_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-10 17:48:20 +00:00
|
|
|
static bool
|
|
|
|
sc_demuxer_recv_codec_id(struct sc_demuxer *demuxer, uint32_t *codec_id) {
|
|
|
|
uint8_t data[4];
|
|
|
|
ssize_t r = net_recv_all(demuxer->socket, data, 4);
|
|
|
|
if (r < 4) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*codec_id = sc_read32be(data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-03-11 08:21:49 +00:00
|
|
|
static bool
|
|
|
|
sc_demuxer_recv_video_size(struct sc_demuxer *demuxer, uint32_t *width,
|
|
|
|
uint32_t *height) {
|
|
|
|
uint8_t data[8];
|
|
|
|
ssize_t r = net_recv_all(demuxer->socket, data, 8);
|
|
|
|
if (r < 8) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*width = sc_read32be(data);
|
|
|
|
*height = sc_read32be(data + 4);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:52:22 +00:00
|
|
|
static bool
|
2022-02-02 19:51:07 +00:00
|
|
|
sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
|
2023-06-01 07:01:52 +00:00
|
|
|
// The video and audio streams contain a sequence of raw packets (as
|
|
|
|
// provided by MediaCodec), each prefixed with a "meta" header.
|
2019-03-02 15:43:43 +00:00
|
|
|
//
|
|
|
|
// The "meta" header length is 12 bytes:
|
|
|
|
// [. . . . . . . .|. . . .]. . . . . . . . . . . . . . . ...
|
|
|
|
// <-------------> <-----> <-----------------------------...
|
|
|
|
// PTS packet raw packet
|
|
|
|
// size
|
|
|
|
//
|
|
|
|
// It is followed by <packet_size> bytes containing the packet/frame.
|
2022-02-11 18:31:01 +00:00
|
|
|
//
|
|
|
|
// The most significant bits of the PTS are used for packet flags:
|
|
|
|
//
|
|
|
|
// byte 7 byte 6 byte 5 byte 4 byte 3 byte 2 byte 1 byte 0
|
2022-02-11 18:33:35 +00:00
|
|
|
// CK...... ........ ........ ........ ........ ........ ........ ........
|
|
|
|
// ^^<------------------------------------------------------------------->
|
|
|
|
// || PTS
|
2022-07-20 09:39:55 +00:00
|
|
|
// | `- key frame
|
|
|
|
// `-- config packet
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2022-02-11 20:34:58 +00:00
|
|
|
uint8_t header[SC_PACKET_HEADER_SIZE];
|
|
|
|
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
|
|
|
|
if (r < SC_PACKET_HEADER_SIZE) {
|
2019-07-30 23:55:32 +00:00
|
|
|
return false;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2022-02-12 08:12:46 +00:00
|
|
|
uint64_t pts_flags = sc_read64be(header);
|
|
|
|
uint32_t len = sc_read32be(&header[8]);
|
2019-11-27 20:11:40 +00:00
|
|
|
assert(len);
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2019-07-30 23:55:32 +00:00
|
|
|
if (av_new_packet(packet, len)) {
|
2021-11-24 21:06:11 +00:00
|
|
|
LOG_OOM();
|
2019-07-30 23:55:32 +00:00
|
|
|
return false;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2022-02-02 19:51:07 +00:00
|
|
|
r = net_recv_all(demuxer->socket, packet->data, len);
|
2019-11-27 12:39:42 +00:00
|
|
|
if (r < 0 || ((uint32_t) r) < len) {
|
2019-07-30 23:55:32 +00:00
|
|
|
av_packet_unref(packet);
|
|
|
|
return false;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2022-02-11 18:31:01 +00:00
|
|
|
if (pts_flags & SC_PACKET_FLAG_CONFIG) {
|
|
|
|
packet->pts = AV_NOPTS_VALUE;
|
|
|
|
} else {
|
|
|
|
packet->pts = pts_flags & SC_PACKET_PTS_MASK;
|
|
|
|
}
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2022-02-11 18:33:35 +00:00
|
|
|
if (pts_flags & SC_PACKET_FLAG_KEY_FRAME) {
|
|
|
|
packet->flags |= AV_PKT_FLAG_KEY;
|
|
|
|
}
|
|
|
|
|
2022-02-11 18:35:47 +00:00
|
|
|
packet->dts = packet->pts;
|
2019-07-30 23:55:32 +00:00
|
|
|
return true;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 23:55:32 +00:00
|
|
|
static int
|
2022-02-02 19:51:07 +00:00
|
|
|
run_demuxer(void *data) {
|
|
|
|
struct sc_demuxer *demuxer = data;
|
2019-07-30 23:55:32 +00:00
|
|
|
|
2023-02-10 17:54:46 +00:00
|
|
|
// Flag to report end-of-stream (i.e. device disconnected)
|
2023-02-28 20:19:43 +00:00
|
|
|
enum sc_demuxer_status status = SC_DEMUXER_STATUS_ERROR;
|
2023-02-10 17:54:46 +00:00
|
|
|
|
2023-02-10 17:48:20 +00:00
|
|
|
uint32_t raw_codec_id;
|
|
|
|
bool ok = sc_demuxer_recv_codec_id(demuxer, &raw_codec_id);
|
|
|
|
if (!ok) {
|
2023-02-18 17:09:18 +00:00
|
|
|
LOGE("Demuxer '%s': stream disabled due to connection error",
|
|
|
|
demuxer->name);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (raw_codec_id == 0) {
|
|
|
|
LOGW("Demuxer '%s': stream explicitly disabled by the device",
|
|
|
|
demuxer->name);
|
2023-03-02 08:20:37 +00:00
|
|
|
sc_packet_source_sinks_disable(&demuxer->packet_source);
|
2023-02-28 20:19:43 +00:00
|
|
|
status = SC_DEMUXER_STATUS_DISABLED;
|
2023-02-10 17:48:20 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-02-23 20:27:11 +00:00
|
|
|
if (raw_codec_id == 1) {
|
|
|
|
LOGE("Demuxer '%s': stream configuration error on the device",
|
|
|
|
demuxer->name);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-02-10 17:48:20 +00:00
|
|
|
enum AVCodecID codec_id = sc_demuxer_to_avcodec_id(raw_codec_id);
|
2023-02-03 11:35:37 +00:00
|
|
|
if (codec_id == AV_CODEC_ID_NONE) {
|
2023-02-18 17:09:18 +00:00
|
|
|
LOGE("Demuxer '%s': stream disabled due to unsupported codec",
|
|
|
|
demuxer->name);
|
2023-03-02 08:20:37 +00:00
|
|
|
sc_packet_source_sinks_disable(&demuxer->packet_source);
|
2023-02-03 11:35:37 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AVCodec *codec = avcodec_find_decoder(codec_id);
|
2019-03-02 15:43:43 +00:00
|
|
|
if (!codec) {
|
2023-02-18 17:09:18 +00:00
|
|
|
LOGE("Demuxer '%s': stream disabled due to missing decoder",
|
|
|
|
demuxer->name);
|
2023-03-02 08:20:37 +00:00
|
|
|
sc_packet_source_sinks_disable(&demuxer->packet_source);
|
2019-03-02 15:43:43 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-03-10 18:25:45 +00:00
|
|
|
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_ctx) {
|
|
|
|
LOG_OOM();
|
2023-02-10 17:45:31 +00:00
|
|
|
goto end;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2023-03-10 18:25:45 +00:00
|
|
|
codec_ctx->flags |= AV_CODEC_FLAG_LOW_DELAY;
|
|
|
|
|
|
|
|
if (codec->type == AVMEDIA_TYPE_VIDEO) {
|
2023-03-11 08:21:49 +00:00
|
|
|
uint32_t width;
|
|
|
|
uint32_t height;
|
|
|
|
ok = sc_demuxer_recv_video_size(demuxer, &width, &height);
|
|
|
|
if (!ok) {
|
|
|
|
goto finally_free_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_ctx->width = width;
|
|
|
|
codec_ctx->height = height;
|
2023-03-10 18:25:45 +00:00
|
|
|
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
|
|
} else {
|
|
|
|
// Hardcoded audio properties
|
|
|
|
#ifdef SCRCPY_LAVU_HAS_CHLAYOUT
|
|
|
|
codec_ctx->ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_STEREO;
|
|
|
|
#else
|
|
|
|
codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
|
|
|
|
codec_ctx->channels = 2;
|
|
|
|
#endif
|
|
|
|
codec_ctx->sample_rate = 48000;
|
2023-11-07 12:09:47 +00:00
|
|
|
|
|
|
|
if (raw_codec_id == SC_CODEC_ID_FLAC) {
|
|
|
|
// The sample_fmt is not set by the FLAC decoder
|
|
|
|
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
|
|
|
}
|
2023-03-10 18:25:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
|
|
|
|
LOGE("Demuxer '%s': could not open codec", demuxer->name);
|
|
|
|
goto finally_free_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sc_packet_source_sinks_open(&demuxer->packet_source, codec_ctx)) {
|
|
|
|
goto finally_free_context;
|
|
|
|
}
|
|
|
|
|
2023-02-18 16:37:58 +00:00
|
|
|
// Config packets must be merged with the next non-config packet only for
|
|
|
|
// video streams
|
|
|
|
bool must_merge_config_packet = codec->type == AVMEDIA_TYPE_VIDEO;
|
|
|
|
|
2023-02-10 21:52:40 +00:00
|
|
|
struct sc_packet_merger merger;
|
2023-02-18 16:37:58 +00:00
|
|
|
|
|
|
|
if (must_merge_config_packet) {
|
|
|
|
sc_packet_merger_init(&merger);
|
|
|
|
}
|
2023-02-10 21:52:40 +00:00
|
|
|
|
2021-06-14 07:07:49 +00:00
|
|
|
AVPacket *packet = av_packet_alloc();
|
|
|
|
if (!packet) {
|
2021-11-24 21:06:11 +00:00
|
|
|
LOG_OOM();
|
2023-02-10 22:18:09 +00:00
|
|
|
goto finally_close_sinks;
|
2021-06-14 07:07:49 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 23:55:32 +00:00
|
|
|
for (;;) {
|
2022-02-02 19:51:07 +00:00
|
|
|
bool ok = sc_demuxer_recv_packet(demuxer, packet);
|
2019-07-30 23:55:32 +00:00
|
|
|
if (!ok) {
|
|
|
|
// end of stream
|
2023-02-28 20:19:43 +00:00
|
|
|
status = SC_DEMUXER_STATUS_EOS;
|
2019-07-30 23:55:32 +00:00
|
|
|
break;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-18 16:37:58 +00:00
|
|
|
if (must_merge_config_packet) {
|
|
|
|
// Prepend any config packet to the next media packet
|
|
|
|
ok = sc_packet_merger_merge(&merger, packet);
|
|
|
|
if (!ok) {
|
|
|
|
av_packet_unref(packet);
|
|
|
|
break;
|
|
|
|
}
|
2023-02-10 21:52:40 +00:00
|
|
|
}
|
|
|
|
|
2023-03-02 08:20:37 +00:00
|
|
|
ok = sc_packet_source_sinks_push(&demuxer->packet_source, packet);
|
2021-06-14 07:07:49 +00:00
|
|
|
av_packet_unref(packet);
|
2019-07-30 23:55:32 +00:00
|
|
|
if (!ok) {
|
2023-03-02 08:20:37 +00:00
|
|
|
// The sink already logged its concrete error
|
2019-03-02 15:43:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-18 23:13:54 +00:00
|
|
|
LOGD("Demuxer '%s': end of frames", demuxer->name);
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2023-02-18 16:37:58 +00:00
|
|
|
if (must_merge_config_packet) {
|
|
|
|
sc_packet_merger_destroy(&merger);
|
|
|
|
}
|
2019-07-30 23:55:32 +00:00
|
|
|
|
2021-06-14 07:07:49 +00:00
|
|
|
av_packet_free(&packet);
|
2021-04-11 13:01:05 +00:00
|
|
|
finally_close_sinks:
|
2023-03-02 08:20:37 +00:00
|
|
|
sc_packet_source_sinks_close(&demuxer->packet_source);
|
2023-03-10 18:25:45 +00:00
|
|
|
finally_free_context:
|
|
|
|
// This also calls avcodec_close() internally
|
|
|
|
avcodec_free_context(&codec_ctx);
|
2019-03-02 15:43:43 +00:00
|
|
|
end:
|
2023-02-28 20:19:43 +00:00
|
|
|
demuxer->cbs->on_ended(demuxer, status, demuxer->cbs_userdata);
|
2021-05-16 13:32:31 +00:00
|
|
|
|
2019-03-02 15:43:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-02 19:09:56 +00:00
|
|
|
void
|
2023-02-18 23:13:54 +00:00
|
|
|
sc_demuxer_init(struct sc_demuxer *demuxer, const char *name, sc_socket socket,
|
2022-02-02 19:51:07 +00:00
|
|
|
const struct sc_demuxer_callbacks *cbs, void *cbs_userdata) {
|
2023-02-06 09:33:47 +00:00
|
|
|
assert(socket != SC_SOCKET_NONE);
|
|
|
|
|
2023-02-18 23:13:54 +00:00
|
|
|
demuxer->name = name; // statically allocated
|
2022-02-02 19:51:07 +00:00
|
|
|
demuxer->socket = socket;
|
2023-03-02 08:20:37 +00:00
|
|
|
sc_packet_source_init(&demuxer->packet_source);
|
2021-05-16 13:32:31 +00:00
|
|
|
|
2023-02-10 17:54:46 +00:00
|
|
|
assert(cbs && cbs->on_ended);
|
2021-05-16 13:32:31 +00:00
|
|
|
|
2022-02-02 19:51:07 +00:00
|
|
|
demuxer->cbs = cbs;
|
|
|
|
demuxer->cbs_userdata = cbs_userdata;
|
2021-04-11 13:01:05 +00:00
|
|
|
}
|
|
|
|
|
2019-03-02 22:52:22 +00:00
|
|
|
bool
|
2022-02-02 19:51:07 +00:00
|
|
|
sc_demuxer_start(struct sc_demuxer *demuxer) {
|
2023-02-18 23:13:54 +00:00
|
|
|
LOGD("Demuxer '%s': starting thread", demuxer->name);
|
2019-03-02 15:43:43 +00:00
|
|
|
|
2022-02-02 19:51:07 +00:00
|
|
|
bool ok = sc_thread_create(&demuxer->thread, run_demuxer, "scrcpy-demuxer",
|
|
|
|
demuxer);
|
2021-01-31 17:24:35 +00:00
|
|
|
if (!ok) {
|
2023-02-18 23:13:54 +00:00
|
|
|
LOGE("Demuxer '%s': could not start thread", demuxer->name);
|
2019-03-02 22:52:22 +00:00
|
|
|
return false;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
2019-03-02 22:52:22 +00:00
|
|
|
return true;
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|
|
|
|
|
2019-03-02 19:09:56 +00:00
|
|
|
void
|
2022-02-02 19:51:07 +00:00
|
|
|
sc_demuxer_join(struct sc_demuxer *demuxer) {
|
|
|
|
sc_thread_join(&demuxer->thread, NULL);
|
2019-03-02 15:43:43 +00:00
|
|
|
}
|