Skip to content

Commit

Permalink
obs-outputs: Fix writing MP4/MOV audio with sample rates > 65535
Browse files Browse the repository at this point in the history
  • Loading branch information
derrod committed Dec 30, 2024
1 parent cab410b commit 45e03de
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 2 deletions.
2 changes: 1 addition & 1 deletion plugins/obs-outputs/mp4-mux-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct mp4_track {
/* Time Base (1/FPS for video, 1/sample rate for audio) */
uint32_t timebase_num;
uint32_t timebase_den;
/* Output timescale calculated from time base (Video only) */
/* Output timescale calculated from time base */
uint32_t timescale;

/* First PTS this track has seen (in track timescale) */
Expand Down
13 changes: 12 additions & 1 deletion plugins/obs-outputs/mp4-mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,15 @@ static inline void mp4_write_audio_sample_entry(struct mp4_mux *mux, struct mp4_
s_wb16(s, is_mov && !is_pcm ? -2 : 0); // pre_defined (compression ID in MOV)
s_wb16(s, 0); // reserved

/* The sample rate field is limited to 16-bits. Technically version 1 supports a "srat" box wich
* provides 32 bits, but this is not supported by most software (including FFmpeg and Chromium).
* For encoded codecs (AAC etc.), the sample rate can be read from the encoded data itself.
* For PCM FFmpeg will try to use the timescale as sample rate. */
if (sample_rate > UINT16_MAX) {
warn("Sample rate too high for MP4, file may not play back correctly.");
sample_rate = 0;
}

s_wb32(s, sample_rate << 16); // samplerate

/* MOV-only data: https://developer.apple.com/documentation/quicktime-file-format/sound_sample_description_version_1 */
Expand Down Expand Up @@ -1226,8 +1235,10 @@ static size_t mp4_write_mov_audio_tag(struct mp4_mux *mux, struct mp4_track *tra

const char *tag = NULL;
audio_t *audio = obs_encoder_audio(track->encoder);
uint32_t sample_rate = audio_output_get_sample_rate(audio);
size_t channels = audio_output_get_channels(audio);
// More than 2 channels requires v2
uint8_t version = audio_output_get_channels(audio) > 2 ? 2 : 1;
uint8_t version = (channels > 2 || sample_rate > UINT16_MAX) ? 2 : 1;

if (track->codec == CODEC_PCM_F32 || track->codec == CODEC_PCM_I16 || track->codec == CODEC_PCM_I24) {
tag = "lpcm";
Expand Down

0 comments on commit 45e03de

Please sign in to comment.