From: Peter Ross <pross@xvid.org> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] Mono ADPCM for EA WVE Files / Fix Framerate Date: Sat, 20 Jul 2024 09:54:37 +1000 Message-ID: <Zpr8vJxGcGGOOd_S@9e5d27e4b9fe9ef6ae1fbb02e4373de4> (raw) In-Reply-To: <CANC4H7BuEJOgXF-1LerhJ5v+LLAd_emag93WHb_ZmqCBAiE+5w@mail.gmail.com> [-- Attachment #1.1: Type: text/plain, Size: 8647 bytes --] On Fri, Jul 19, 2024 at 07:34:18AM -0400, redacted redacted wrote: > Hello there, > > The Sims 1: Unleashed makes use of WVE files for its intro videos. > Two of the files for the game use Mono ADPCM audio instead of Stereo. > However, FFmpeg's ADPCM_EA codec always expects the files to be in Stereo. can you post a sample file somewhere > In addition, they're supposed to play at 30 fps, but the EA demuxer assumes > 15 by default. > It appears the framerate is set with the use of the 0x1B code in the SCHl / > PT00 header. nice find > I have made changes in the patch attached to fix these problems. thx for sharing. the patch needs a small amount of improvement. see below for my suggestions. > From 306f9db010cf000eb8477aca243fc970f5b95df8 Mon Sep 17 00:00:00 2001 > From: aaron <aaronrules5alt@gmail.com> > Date: Fri, 19 Jul 2024 07:30:10 -0400 > Subject: [PATCH 1/1] Mono ADPCM for EA WVE Files / Fix Framerate > > --- > libavcodec/adpcm.c | 57 +++++++++++++++++++++++++----------- > libavformat/electronicarts.c | 12 ++++++-- > 2 files changed, 50 insertions(+), 19 deletions(-) > > diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c > index f63afefd63..238214877d 100644 > --- a/libavcodec/adpcm.c > +++ b/libavcodec/adpcm.c > @@ -262,7 +262,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) > break; > case AV_CODEC_ID_ADPCM_DTK: > case AV_CODEC_ID_ADPCM_EA: > - min_channels = 2; > + min_channels = 1; > break; > case AV_CODEC_ID_ADPCM_AFC: > case AV_CODEC_ID_ADPCM_EA_R1: > @@ -914,10 +914,12 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, > bytestream2_seek(gb, -8, SEEK_CUR); > break; > case AV_CODEC_ID_ADPCM_EA: > + /* Stereo is 30 bytes per block */ > + /* Mono is 15 bytes per block */ > has_coded_samples = 1; > *coded_samples = bytestream2_get_le32(gb); > *coded_samples -= *coded_samples % 28; > - nb_samples = (buf_size - 12) / 30 * 28; > + nb_samples = (buf_size - 12) / (ch == 2 ? 30 : 15) * 28; > break; > case AV_CODEC_ID_ADPCM_IMA_EA_EACS: > has_coded_samples = 1; > @@ -1652,10 +1654,10 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, > int coeff1l, coeff2l, coeff1r, coeff2r; > int shift_left, shift_right; > > - /* Each EA ADPCM frame has a 12-byte header followed by 30-byte pieces, > - each coding 28 stereo samples. */ > - > - if (channels != 2) > + /* Each EA ADPCM frame has a 12-byte header followed by 30-byte (stereo) or 15-byte (mono) pieces, > + each coding 28 stereo/mono samples. */ > + > + if (channels != 2 && channels != 1) > return AVERROR_INVALIDDATA; > > current_left_sample = sign_extend(bytestream2_get_le16u(&gb), 16); > @@ -1665,37 +1667,58 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, > > for (int count1 = 0; count1 < nb_samples / 28; count1++) { > int byte = bytestream2_get_byteu(&gb); > - coeff1l = ea_adpcm_table[ byte >> 4 ]; > - coeff2l = ea_adpcm_table[(byte >> 4 ) + 4]; > + coeff1l = ea_adpcm_table[ byte >> 4 ]; > + coeff2l = ea_adpcm_table[(byte >> 4) + 4]; these whitespace-only changes shouldn't go in the patch. > coeff1r = ea_adpcm_table[ byte & 0x0F]; > coeff2r = ea_adpcm_table[(byte & 0x0F) + 4]; > > - byte = bytestream2_get_byteu(&gb); > - shift_left = 20 - (byte >> 4); > - shift_right = 20 - (byte & 0x0F); > - > - for (int count2 = 0; count2 < 28; count2++) { > + if (channels == 2){ > + byte = bytestream2_get_byteu(&gb); > + shift_left = 20 - (byte >> 4); > + shift_right = 20 - (byte & 0x0F); > + } else{ > + /* Mono packs the shift into the coefficient byte's lower nibble instead */ > + shift_left = 20 - (byte & 0x0F); > + } > + > + for (int count2 = 0; count2 < ( channels == 2 ? 28 : 14); count2++) { "count2 < ( channels..." looks out of place. drop the space after the parenthesis. > byte = bytestream2_get_byteu(&gb); > next_left_sample = sign_extend(byte >> 4, 4) * (1 << shift_left); > - next_right_sample = sign_extend(byte, 4) * (1 << shift_right); > + next_right_sample = sign_extend(byte, 4) * (1 << shift_right); > > next_left_sample = (next_left_sample + > (current_left_sample * coeff1l) + > (previous_left_sample * coeff2l) + 0x80) >> 8; > + > next_right_sample = (next_right_sample + > (current_right_sample * coeff1r) + > (previous_right_sample * coeff2r) + 0x80) >> 8; > > previous_left_sample = current_left_sample; > current_left_sample = av_clip_int16(next_left_sample); > + > previous_right_sample = current_right_sample; > current_right_sample = av_clip_int16(next_right_sample); > + > *samples++ = current_left_sample; > - *samples++ = current_right_sample; > + ditto for these whitespace-only changes above. > + if (channels == 2){ > + *samples++ = current_right_sample; > + } else { > + next_left_sample = sign_extend(byte, 4) * (1 << shift_left); > + > + next_left_sample = (next_left_sample + > + (current_left_sample * coeff1l) + > + (previous_left_sample * coeff2l) + 0x80) >> 8; > + > + previous_left_sample = current_left_sample; > + current_left_sample = av_clip_int16(next_left_sample); > + > + *samples++ = current_left_sample; > + } > } > } > - > - bytestream2_skip(&gb, 2); // Skip terminating 0x0000 > + bytestream2_skip(&gb, channels == 2 ? 2 : 3); // Skip terminating NULs > ) /* End of CASE */ > CASE(ADPCM_EA_MAXIS_XA, > int coeff[2][2], shift[2]; i suggest splitting this into two patches, one for mono adpcm ea, another for the frame rate fix. > diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c > index f7f6fd4cab..c141a172dd 100644 > --- a/libavformat/electronicarts.c > +++ b/libavformat/electronicarts.c > @@ -86,6 +86,8 @@ typedef struct EaDemuxContext { > enum AVCodecID audio_codec; > int audio_stream_index; > > + int framerate; > + > int bytes; > int sample_rate; > int num_channels; > @@ -198,6 +200,10 @@ static int process_audio_header_elements(AVFormatContext *s) > av_log(s, AV_LOG_DEBUG, "end of header block reached\n"); > in_header = 0; > break; > + case 0x1B: > + ea->framerate = read_arbitrary(pb); > + av_log(s, AV_LOG_DEBUG, "Setting framerate to %u", ea->framerate); > + break; av_log trailing "\n" missing > default: > av_log(s, AV_LOG_DEBUG, > "header element 0x%02x set to 0x%08"PRIx32"\n", > @@ -367,6 +373,8 @@ static int process_ea_header(AVFormatContext *s) > AVIOContext *pb = s->pb; > int i; > > + ea->framerate = 15; > + > for (i = 0; i < 5 && (!ea->audio_codec || !ea->video.codec); i++) { > uint64_t startpos = avio_tell(pb); > int err = 0; > @@ -427,12 +435,12 @@ static int process_ea_header(AVFormatContext *s) > case pQGT_TAG: > case TGQs_TAG: > ea->video.codec = AV_CODEC_ID_TGQ; > - ea->video.time_base = (AVRational) { 1, 15 }; > + ea->video.time_base = (AVRational) { 1, ea->framerate }; > break; > > case pIQT_TAG: > ea->video.codec = AV_CODEC_ID_TQI; > - ea->video.time_base = (AVRational) { 1, 15 }; > + ea->video.time_base = (AVRational) { 1, ea->framerate }; > break; > > case MADk_TAG: > -- -- Peter (A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B) [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] [-- Attachment #2: Type: text/plain, Size: 251 bytes --] _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2024-07-19 23:54 UTC|newest] Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top 2024-07-19 11:34 redacted redacted 2024-07-19 23:54 ` Peter Ross [this message] 2024-07-20 14:19 ` Aaron 2024-07-22 9:36 ` Peter Ross
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=Zpr8vJxGcGGOOd_S@9e5d27e4b9fe9ef6ae1fbb02e4373de4 \ --to=pross@xvid.org \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git