Changes

Jump to navigation Jump to search
6,481 bytes added ,  21:38, 21 October 2019
Line 8: Line 8:  
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
! Cmd || Name || Notes
+
! Cmd || Name
 +
|-
 +
| 1 || [[#OpenContinuousRecorder]]
 
|-
 
|-
| 1 || OpenContinuousRecorder || Takes a total of 0x48-bytes of input and a handle, returns an [[#IContinuousRecorder]].
+
| 2 || [[#OpenGameMovieTrimmer]]
 
|-
 
|-
| 2 || OpenGameMovieTrimmer || Takes a total of 0x8-bytes of input and a handle, returns an [[#IGameMovieTrimmer]].
+
| 3 || [5.0.0+] [[#OpenOffscreenRecorder]]
 
|-
 
|-
| 3 || || Takes a total of 0x8-bytes of input and a handle, returns an [[#IUnknown]].
+
| 101 || [5.0.0+] [[#CreateMovieMaker]]
 
|-
 
|-
| 101 || || Takes a total of 0x10-bytes of input, returns an [[#IMovieMaker]].
+
| 9903 || [5.0.0+] [[#SetOffscreenRecordingMarker]]
 
|}
 
|}
 +
 +
== OpenContinuousRecorder ==
 +
Takes a total of 0x28-bytes of input and a handle, returns an [[#IContinuousRecorder]].
 +
 +
[5.0.0+] Now takes an additional 0x20-bytes of input.
 +
 +
== OpenGameMovieTrimmer ==
 +
Takes an input u64 and a handle, returns an [[#IGameMovieTrimmer]].
 +
 +
== OpenOffscreenRecorder ==
 +
Takes a total of 0x8-bytes of input and a handle, returns an [[#IOffscreenRecorder]].
 +
 +
== CreateMovieMaker ==
 +
Takes a total of 0x10-bytes of input, returns an [[#IMovieMaker]].
 +
 +
== SetOffscreenRecordingMarker ==
 +
Takes an u64 '''marker''' (value from 0 to 14), no output.
 +
 +
Affects the behavior of [[#CompleteOffscreenRecordingFinish]], [[#CompleteOffscreenRecordingFinishEx0]] and [[#CompleteOffscreenRecordingFinishEx1]], forcing them to stop at different stages.
    
== IContinuousRecorder ==
 
== IContinuousRecorder ==
Line 38: Line 59:  
| 13 ||
 
| 13 ||
 
|-
 
|-
| 14 ||
+
| 14 || [5.0.0+]
 
|}
 
|}
 +
 +
[5.0.0+] Cmd11 now takes a total of 0x40-bytes of input.
 +
 +
[8.0.0+] Cmd11/cmd14 no longer take any rawdata input, these now take a type-0x15 input buffer.
    
== IGameMovieTrimmer ==
 
== IGameMovieTrimmer ==
Line 48: Line 73:  
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 1 || BeginTrim
+
| 1 || [[#BeginTrim]]
 
|-
 
|-
| 2 || EndTrim
+
| 2 || [[#EndTrim]]
 
|-
 
|-
| 10 || GetNotTrimmingEvent
+
| 10 || [[#GetNotTrimmingEvent]]
 
|-
 
|-
| 20 || SetThumbnailRgba
+
| 20 || [[#SetThumbnailRgba]]
 
|}
 
|}
 +
 +
Album uses [[Applet_Manager_services#CreateGameMovieTrimmer|CreateGameMovieTrimmer]], and retries using the cmd in a loop on error 0x8D4 with svcSleepThread(100000000) being used first. Then all 4 of these commands are used in that same func: [[#SetThumbnailRgba]] if the input buffer is set, [[#GetNotTrimmingEvent]], [[#BeginTrim]], waits on the event, then [[#EndTrim]] and cleanup.
 +
 +
=== BeginTrim ===
 +
Takes an input s32 '''start''', a s32 '''end''', and a [[#GameMovieId]], no output.
 +
 +
The two s32s are the start/end timestamps in 0.5s units.
 +
 +
=== EndTrim ===
 +
No input, returns an output [[#GameMovieId]].
 +
 +
This just loads the [[#GameMovieId]] from state, when available.
 +
 +
=== GetNotTrimmingEvent ===
 +
No input, returns an output Event handle with autoclear=false.
 +
 +
=== SetThumbnailRgba ===
 +
Takes a type-0x45 input buffer, a s32 '''width''', and a s32 '''height''', no output.
 +
 +
'''width''' must be 1280, '''height''' must be 720, and the buffer size must be at least 0x384000. After this validation, this just copies the input buffer to state with size 0x384000 and returns 0.
    
= grc:d =
 
= grc:d =
 
This is "nn::grcsrv::IRemoteVideoTransfer".
 
This is "nn::grcsrv::IRemoteVideoTransfer".
   −
Added with [[6.0.0]].
+
This was added with [[6.0.0]].
 +
 
 +
The max sessions for this service is 4, and it uses 2 IPC handler threads.
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
! Cmd || Name || Notes
+
! Cmd || Name
 
|-
 
|-
| 1 || || No input/output.
+
| 1 || [[#Initialize]]
 
|-
 
|-
| 2 || || Takes a total of 4-bytes of input and a type-0x6 output buffer, returns a total of 0x10-bytes of output.
+
| 2 || [[#Transfer]]
 
|}
 
|}
   −
= IUnknown =
+
== Initialize ==
 +
No input/output.
 +
 
 +
Begins video stream. This must not be used more than once, even from a different service session: otherwise the sysmodule will assert.
 +
 
 +
== Transfer ==
 +
Takes an u32 '''stream''' (0: video, 1: audio) and a type-0x6 output buffer, returns 2 u32s '''num_frames''' and '''data_size''' and an u64 '''start_timestamp'''.
 +
 
 +
Retrieves stream data from the continuous recorder in use. Video stream writes H.264 NAL units to the output buffer (try <code>ffplay -f h264</code>). Audio stream is PCM16, 2 channels, and sample-rate = 48000Hz. Official code uses buffer size 0x32000 for video, 0x1000 for audio, and multiple threads to read out both streams at the same time.
 +
 
 +
This will block until data is available. This will hang if there is no game title running which has video capture enabled.
 +
 
 +
= IOffscreenRecorder =
 +
This is "nn::grcsrv::IOffscreenRecorder".
 +
 
 +
This was added with [5.0.0+].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 80: Line 142:  
|-
 
|-
 
| 202 || || Takes a total of 0x8-bytes of input, no output.
 
| 202 || || Takes a total of 0x8-bytes of input, no output.
|-
   
|}
 
|}
    
= IMovieMaker =
 
= IMovieMaker =
 
This is "nn::grcsrv::IMovieMaker".
 
This is "nn::grcsrv::IMovieMaker".
 +
 +
This was added with [5.0.0+].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 91: Line 154:  
|-
 
|-
 
| 2 || [[#CreateVideoProxy]]
 
| 2 || [[#CreateVideoProxy]]
 +
|-
 +
| 9 || [7.0.0+] [[#SetAlbumShimLibraryVersion]]
 
|-
 
|-
 
| 10 || [[#OpenOffscreenLayer]]
 
| 10 || [[#OpenOffscreenLayer]]
Line 107: Line 172:  
|-
 
|-
 
| 25 || [[#CompleteOffscreenRecordingFinishEx0]]
 
| 25 || [[#CompleteOffscreenRecordingFinishEx0]]
 +
|-
 +
| 26 || [7.0.0+] [[#CompleteOffscreenRecordingFinishEx1]]
 
|-
 
|-
 
| 30 || [[#GetOffscreenLayerError]]
 
| 30 || [[#GetOffscreenLayerError]]
Line 119: Line 186:  
== CreateVideoProxy ==
 
== CreateVideoProxy ==
 
No input, returns an [[#IHOSBinderDriver]].
 
No input, returns an [[#IHOSBinderDriver]].
 +
 +
== SetAlbumShimLibraryVersion ==
 +
Takes an input u64 [[Capture_services#ShimLibraryVersion|ShimLibraryVersion]], no output.
    
== OpenOffscreenLayer ==
 
== OpenOffscreenLayer ==
Takes an input u64 '''LayerHandle''', returns an output u32.
+
Takes an input u64 '''LayerHandle''', returns an output s32 '''ID'''.
 +
 
 +
This gets the '''ID''' for the [[#IHOSBinderDriver]] returned by [[#CreateVideoProxy]].
    
== CloseOffscreenLayer ==
 
== CloseOffscreenLayer ==
Line 136: Line 208:  
== RequestOffscreenRecordingFinishReady ==
 
== RequestOffscreenRecordingFinishReady ==
 
Takes an input u64 '''LayerHandle''', no output.
 
Takes an input u64 '''LayerHandle''', no output.
 +
 +
This is the first cmd used by official sw when finishing recording. Then it waits on the Event originally loaded from [[#GetOffscreenLayerRecordingFinishReadyEvent]]. Then CompleteOffscreenRecordingFinishEx* is used, depending on the sdk-nso version. On any errors, [[#AbortOffscreenRecording]] is used.
    
== StartOffscreenRecordingEx ==
 
== StartOffscreenRecordingEx ==
Line 141: Line 215:     
== CompleteOffscreenRecordingFinish ==
 
== CompleteOffscreenRecordingFinish ==
Takes an input u64 and a type-0x5 input buffer, no output.
+
Takes an input u64 '''LayerHandle''' and a type-0x5 input buffer, no output.
    
Seems to be unused by official user processes, [[#CompleteOffscreenRecordingFinishEx0]] is used instead.
 
Seems to be unused by official user processes, [[#CompleteOffscreenRecordingFinishEx0]] is used instead.
 +
 +
The input buffer contains the optional ApplicationData for the JPEG thumbnail, size must be <=0x400.
 +
 +
The recorded video will not be accessible via the Album-applet since it's stored separately from other Album data.
    
== CompleteOffscreenRecordingFinishEx0 ==
 
== CompleteOffscreenRecordingFinishEx0 ==
Takes an input u64 '''LayerHandle''' and 2 type-0x5 input buffers, no output.
+
Takes two input s32s '''width'''/'''height''', an input u64 '''LayerHandle''' and 2 type-0x5 input buffers, no output.
   −
== EncodeOffscreenLayerAudioSample ==
+
The input buffers are optional, addr=NULL and size=0 can be used for these. The first buffer is for [[#CompleteOffscreenRecordingFinish|ApplicationData]], the second buffer buffer contains the RGBA8 image thumbnail.
Takes an input u64 '''LayerHandle''' and a type-0x5 input buffer, returns an output u64.
+
 
 +
'''width'''/'''height''' must be 1280x720, these fields are unused afterwards.
 +
 
 +
Besides '''width'''/'''height''', this is the same as [[#CompleteOffscreenRecordingFinish]] except the second buffer is user-specified instead of addr=NULL/size=0.
 +
 
 +
== CompleteOffscreenRecordingFinishEx1 ==
 +
Takes two input s32s '''width'''/'''height''', an input u64 '''LayerHandle''' and two type-0x5 input buffers, returns an output [[Capture_services|ApplicationAlbumEntry]].
 +
 
 +
Same as [[#CompleteOffscreenRecordingFinishEx0]] except the output struct is returned in the cmdreply. Official sw copies the output struct into a "nn::album::AlbumFileEntry".
    
== GetOffscreenLayerError ==
 
== GetOffscreenLayerError ==
 
Takes an input u64 '''LayerHandle''', no output.
 
Takes an input u64 '''LayerHandle''', no output.
 +
 +
== EncodeOffscreenLayerAudioSample ==
 +
Takes an input u64 '''LayerHandle''' and a type-0x5 input buffer, returns an output u64 '''out_size'''.
 +
 +
Official sw enters a loop for handling the user-specified buffer:
 +
* Waits on the Event originally loaded from [[#GetOffscreenLayerAudioEncodeReadyEvent]].
 +
* Uses the cmd with the current buffer_addr+pos and the remaining_size.
 +
* Updates the current pos and remaining_size with the '''out_size'''.
 +
* Repeats the loop until the remaining_size is 0.
    
== GetOffscreenLayerRecordingFinishReadyEvent ==
 
== GetOffscreenLayerRecordingFinishReadyEvent ==
Takes an input u64 '''LayerHandle''', returns an output event handle.
+
Takes an input u64 '''LayerHandle''', returns an output event handle with autoclear disabled.
    
== GetOffscreenLayerAudioEncodeReadyEvent ==
 
== GetOffscreenLayerAudioEncodeReadyEvent ==
Takes an input u64 '''LayerHandle''', returns an output event handle.
+
Takes an input u64 '''LayerHandle''', returns an output event handle with autoclear disabled.
    
= OffscreenRecordingParameter =
 
= OffscreenRecordingParameter =
This is a 0x80-byte struct.
+
This is "nn::grcsrv::OffscreenRecordingParameter".
 +
 
 +
This is a 0x80-byte struct. "nn::grc::OffscreenRecordingParameter" and "nn::album::MovieMakerMovieParameter" are identical to this.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description || Default value
 +
|-
 +
| 0x0 || 0x10 || ? || 0
 +
|-
 +
| 0x10 || 0x4 || Unknown, must match 0x103. || 0x103
 +
|-
 +
| 0x14 || 0x4 || s32 VideoBitRate, 0 is invalid. || 8000000
 +
|-
 +
| 0x18 || 0x4 || s32 VideoWidth, must match 1280 or 1920. || 1280
 +
|-
 +
| 0x1C || 0x4 || s32 VideoHeight, must match 720 or 1080. || 720
 +
|-
 +
| 0x20 || 0x4 || s32 VideoFrameRate, must match 30 or 60. || 30
 +
|-
 +
| 0x24 || 0x4 || s32 VideoKeyFrameInterval, 0 is invalid. || 30
 +
|-
 +
| 0x28 || 0x4 || s32 AudioBitRate || 128000 ([5.0.0-5.1.0] 1536000)
 +
|-
 +
| 0x2C || 0x4 || s32 AudioSampleRate, 0 is invalid. || 48000
 +
|-
 +
| 0x30 || 0x4 || s32 AudioChannelCount, must match 2. || 2
 +
|-
 +
| 0x34 || 0x4 || "nn::audio::SampleFormat" AudioSampleFormat, must match 2. || 2
 +
|-
 +
| 0x38 || 0x4 || "nn::album::ImageOrientation" VideoImageOrientation. || 0
 +
|-
 +
| 0x3C || 0x44 || ? || 0
 +
|}
 +
 
 +
The above default values are initialized by the official user-process via sdk-nso funcs "nn::album::MovieMakerMovieParameter::GetDefaultValue()" / "nn::album::MovieMakerMovieParameter::MovieMakerMovieParameter()" (both funcs are identical).
 +
 
 +
= GameMovieId =
 +
This is "nn::grcsrv::GameMovieId".
 +
 
 +
This is a 0x40-byte struct.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x18 || Same as the last 0x18-bytes of [[Capture_services|AlbumEntry]].
 +
|-
 +
| 0x18 || 0x28 || Unused, always zero.
 +
|}
    
= IHOSBinderDriver =
 
= IHOSBinderDriver =

Navigation menu