Commit Graph

67 Commits (7de062221465fef6c6be5998b3884bdc833c8526)

Author SHA1 Message Date
Romain Vimont 7de0622214 Add audio recording support
Make the recorder accept two input sources (video and audio), and mux
them into a single file.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
1 year ago
Romain Vimont 3d29f6ef06 Rename video-specific variables in recorder
This paves the way to add audio-specific variables.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
1 year ago
Romain Vimont f9efe48aac Refactor recorder logic
Process the initial config packet (necessary to write the header)
separately.
1 year ago
Romain Vimont 4b246cd963 Move last packet recording
Write the last packet at the end.
1 year ago
Romain Vimont 3c407773e9 Add start() function for recorder
For consistency with the other components, do not start the internal
thread from an init() function.
1 year ago
Romain Vimont a039124d5d Open recording file from the recorder thread
The recorder opened the target file from the packet sink open()
callback, called by the demuxer. Only then the recorder thread was
started.

One golden rule for the recorder is to never block the demuxer for I/O,
because it would impact mirroring. This rule is respected on recording
packets, but not for the initial recorder opening.

Therefore, start the recorder thread from sc_recorder_init(), open the
file immediately from the recorder thread, then make it wait for the
stream to start (on packet sink open()).

Now that the recorder can report errors directly (rather than making the
demuxer call fail), it is possible to report file opening error even
before the packet sink is open.
1 year ago
Romain Vimont 6b5dfef923 Inline packet_sink impl in recorder
Remove useless wrappers.
1 year ago
Romain Vimont fb29135591 Initialize recorder fields from init()
The recorder has two initialization phases: one to initialize the
concrete recorder object, and one to open its packet_sink trait.

Initialize mutex and condvar as part of the object initialization.

If there were several packet_sink traits (spoiler: one for video, one
for audio), then the mutex and condvar would still be initialized only
once.
1 year ago
Romain Vimont b1b33e3eaf Report recorder errors
Stop scrcpy on recorder errors.

It was previously indirectly stopped by the demuxer, which failed to
push packets to a recorder in error. Report it directly instead:
 - it avoids to wait for the next demuxer call;
 - it will allow to open the target file from a separate thread and stop
   immediately on any I/O error.
1 year ago
Romain Vimont db5751a76a Move previous packet to a local variable
It is only used from run_recorder().
1 year ago
Romain Vimont b6744e7887 Move pts_origin to a local variable
It is only used from run_recorder().
1 year ago
Romain Vimont 181fb555bb Change PTS origin type from uint64_t to int64_t
It is initialized from AVPacket.pts, which is an int64_t.
1 year ago
Romain Vimont 1c82c3923d Compute relative PTS on the client-side
The PTS received from MediaCodec are expressed relative to an arbitrary
clock origin. We consider the PTS of the first frame to be 0, and the
PTS of every other frame is relative to this first PTS (note that the
PTS is only used for recording, it is ignored for mirroring).

For simplicity, this relative PTS was computed on the server-side.

To prepare support for multiple stream (video and audio), send the
packet with its original PTS, and handle the PTS offset on the
client-side (by the recorder).

Since we can't know in advance which stream will produce the first
packet with the lowest PTS (a packet received later on one stream may
have a PTS lower than a packet received earlier on another stream),
computing the PTS on the server-side would require unnecessary waiting.
1 year ago
Romain Vimont 61b6324ee9 Remove LOGC()
It is not clear when to use LOGC() rather than LOGE(). Always use
LOGE().

Moreover, enum sc_log_level has no "critical" log level.
2 years ago
Romain Vimont 4ee62abe1d Use sc_ prefix for recorder 2 years ago
Romain Vimont 3ada5c51bc Rename scrcpy threads
Prefix the name of threads by "scrcpy-". This improves readability in
the output of `top -H` for example.

Limit the thread names to 16 bytes, because it is limited on some
platforms.
3 years ago
Romain Vimont 3653fb6b15 Add OutOfMemory log helper
Add a special LOG_OOM() function to log all OutOfMemory errors (i.e.
allocations returning NULL).
3 years ago
Romain Vimont 057c7a4df4 Move str_util to str
Simplify naming.
3 years ago
Romain Vimont 979ce64dc0 Improve string util API
Use prefixed names and improve documentation.
3 years ago
Romain Vimont 4c4381de4c Use sc_ prefix for size, position and point 3 years ago
Romain Vimont 31131039bb Add missing includes
Refs #2616 <https://github.com/Genymobile/scrcpy/issues/2616>
3 years ago
Romain Vimont daf90d33d5 Fix code style
Make the code fit into 80 columns.
3 years ago
Romain Vimont 099cba07f0 Rename queue to sc_queue
Add a scrcpy-specific prefix.
3 years ago
Romain Vimont e9096e3e34 Remove unnecessary calls to av_packet_unref()
av_packet_free() already calls av_packet_unref().
3 years ago
Romain Vimont 4af317d40d Allocate AVPacket for recorder
From FFmpeg/doc/APIchanges:

    2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h
      Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will
      no longer be a part of the public ABI.

Refs #2302 <https://github.com/Genymobile/scrcpy/issues/2302>
3 years ago
Romain Vimont 151bc16644 Use strlist_contains() to find a muxer
The AVOutputFormat name is a string list: it contains names separated by
',' (possibly only one).
3 years ago
Romain Vimont 243854a408 Fix recorder comment 3 years ago
Romain Vimont 2a5dfc1c17 Handle errors using gotos in recorder_open()
There are many initializations in recorder_open(). Handle RAII-like
deinitialization using gotos.
3 years ago
Romain Vimont e3fccc5a5e Initialize recorder fields on open
Only initialize ops and parameters copy from recorder_init(). It was
inconsistent to initialize some fields from _init() and some others from
_open().
3 years ago
Romain Vimont f7a1b67d66 Make stream push packets to sinks
Now that decoder and recorder implement the packet sink trait, make
stream push packets to the sinks without depending on the concrete sink
types.
3 years ago
Romain Vimont 5980183a33 Expose recorder as packet sink
Make recorder implement the packet sink trait.

This will allow the stream to push packets without depending on the
concrete sink type.
3 years ago
Romain Vimont fe8de893ca Privatize recorder threading
The fact that the recorder uses a separate thread is an internal detail,
so the functions _start(), _stop() and _join() should not be exposed.

Instead, start the thread on _open() and _stop()+_join() on close().

This paves the way to expose the recorder as a packet sink trait.
3 years ago
Romain Vimont a974483c15 Reorder recorder functions
This will make further commits more readable.
3 years ago
Romain Vimont 5d9e96dc4e Remove compat with old FFmpeg codec params API
The new API has been introduced in 2016 in libavformat 57.xx, it's very
old.

This will avoid to maintain two code paths for codec parameters.
3 years ago
Romain Vimont 21b590b766 Write trailer from recorder thread
The recorder thread wrote the whole content except the trailer, which
was odd.
3 years ago
Romain Vimont d0983db592 Make internal recorder function static 3 years ago
Romain Vimont f6320c7e31 Wrap SDL thread functions into scrcpy-specific API
The goal is to expose a consistent API for system tools, and paves the
way to make the "core" independant of SDL in the future.
3 years ago
Romain Vimont 30e619d37f Replace SDL_strdup() by strdup()
The functions SDL_malloc(), SDL_free() and SDL_strdup() were used only
because strdup() was not available everywhere.

Now that it is available, use the native version of these functions.
3 years ago
Romain Vimont 59feb2a15c Group common includes into common.h
Include config.h and compat.h in common.h, and include common.h from all
source files.
4 years ago
Romain Vimont a65ebceac1 Add missing mutex unlock on error
Fixes #1770 <https://github.com/Genymobile/scrcpy/issues/1770>

Reported-by: lordnn
4 years ago
Romain Vimont 0ba74fbd9a Make scrcpy.h independant of other headers
The header scrcpy.h is intended to be the "public" API. It should not
depend on other internal headers.

Therefore, declare all required structs in this header and adapt
internal code.
4 years ago
Romain Vimont 510caff0cd Replace SDL_assert() by assert()
SDL_assert() open a dialog on assertion failure.

There is no reason not to use assert() directly.
5 years ago
Romain Vimont dfd0707a29 Move utilities to util/ 5 years ago
Romain Vimont 771bd8404d Do not write invalid packet duration
Configuration packets have no PTS. Do not compute a packet duration from
their PTS.

Fixes recording to mp4 on device rotation.
5 years ago
Romain Vimont b08a98324d Fix segfault on empty file recorded
Write the file trailer only if the file header have been written, to
avoid a segfault in libav.

Fixes <https://github.com/Genymobile/scrcpy/issues/918>.
5 years ago
Romain Vimont 95fd64b5de Add scrcpy version in recorded video metadata
It might help to understand problems in recorded videos.
5 years ago
Romain Vimont 1f8ba1ca79 Include config.h everywhere
Ref: <https://github.com/Genymobile/scrcpy/issues/829>

Suggested-by: Louis Kruger <louisk@gmail.com>
5 years ago
Romain Vimont a9c8fa305d Fix segfault on recording with old FFmpeg
The AVPacket fields side_data and side_data_elems were not initialized
by av_packet_ref() in old FFmpeg versions (prior to [1]).

As a consequence, on av_packet_unref(), side_data was freed, causing a
segfault.

Fixes <https://github.com/Genymobile/scrcpy/issues/707>

[1]: <http://git.videolan.org/gitweb.cgi/ffmpeg.git/?p=ffmpeg.git;a=commitdiff;h=3b4026e15110547892d5d770b6b43c9e34df458f>
5 years ago
Romain Vimont 8507fea271 Record a packet with its duration
Record a packet only once the following has been received, so that we
can set its duration before muxing it.

Fixes <https://github.com/Genymobile/scrcpy/issues/702>
5 years ago
Romain Vimont 5e4ccfd832 Use generic FIFO queue for recording
Replace the specific recording queue by the new generic FIFO queue
implementation.
5 years ago