You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	ADPCM IMA Radical decoder
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
		| @@ -44,6 +44,7 @@ version <next>: | ||||
| - ADP demuxer | ||||
| - RSD demuxer | ||||
| - RedSpark demuxer | ||||
| - ADPCM IMA Radical decoder | ||||
|  | ||||
|  | ||||
| version 1.2: | ||||
|   | ||||
| @@ -772,6 +772,7 @@ following image formats are supported: | ||||
|     @tab Used in some Sega Saturn console games. | ||||
| @item ADPCM IMA Duck DK4     @tab     @tab  X | ||||
|     @tab Used in some Sega Saturn console games. | ||||
| @item ADPCM IMA Radical      @tab     @tab  X | ||||
| @item ADPCM Microsoft        @tab  X  @tab  X | ||||
| @item ADPCM MS IMA           @tab  X  @tab  X | ||||
| @item ADPCM Nintendo Gamecube AFC  @tab     @tab  X | ||||
|   | ||||
| @@ -590,6 +590,7 @@ OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER)      += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER)      += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER)       += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER)       += adpcmenc.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_RAD_DECODER)      += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER)   += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER)      += adpcm.o adpcm_data.o | ||||
| OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER)      += adpcmenc.o adpcm_data.o | ||||
|   | ||||
| @@ -551,6 +551,11 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, | ||||
|             buf_size = FFMIN(buf_size, avctx->block_align); | ||||
|         nb_samples = 1 + (buf_size - 4 * ch) * 2 / ch; | ||||
|         break; | ||||
|     case AV_CODEC_ID_ADPCM_IMA_RAD: | ||||
|         if (avctx->block_align > 0) | ||||
|             buf_size = FFMIN(buf_size, avctx->block_align); | ||||
|         nb_samples = (buf_size - 4 * ch) * 2 / ch; | ||||
|         break; | ||||
|     case AV_CODEC_ID_ADPCM_IMA_WAV: | ||||
|         if (avctx->block_align > 0) | ||||
|             buf_size = FFMIN(buf_size, avctx->block_align); | ||||
| @@ -912,6 +917,31 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | ||||
|             *samples++ = adpcm_ima_oki_expand_nibble(&c->status[st], v & 0x0F); | ||||
|         } | ||||
|         break; | ||||
|     case AV_CODEC_ID_ADPCM_IMA_RAD: | ||||
|         for (channel = 0; channel < avctx->channels; channel++) { | ||||
|             cs = &c->status[channel]; | ||||
|             cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); | ||||
|             cs->predictor  = sign_extend(bytestream2_get_le16u(&gb), 16); | ||||
|             if (cs->step_index > 88u){ | ||||
|                 av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", | ||||
|                        channel, cs->step_index); | ||||
|                 return AVERROR_INVALIDDATA; | ||||
|             } | ||||
|         } | ||||
|         for (n = 0; n < nb_samples / 2; n++) { | ||||
|             int byte[2]; | ||||
|  | ||||
|             byte[0] = bytestream2_get_byteu(&gb); | ||||
|             if (st) | ||||
|                 byte[1] = bytestream2_get_byteu(&gb); | ||||
|             for(channel = 0; channel < avctx->channels; channel++) { | ||||
|                 *samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] & 0x0F, 3); | ||||
|             } | ||||
|             for(channel = 0; channel < avctx->channels; channel++) { | ||||
|                 *samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] >> 4  , 3); | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     case AV_CODEC_ID_ADPCM_IMA_WS: | ||||
|         if (c->vqa_version == 3) { | ||||
|             for (channel = 0; channel < avctx->channels; channel++) { | ||||
| @@ -1489,6 +1519,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI,     sample_fmts_s16,  adpcm_ima_oki,     "ADPCM IMA Dialogic OKI"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT,      sample_fmts_s16p, adpcm_ima_qt,      "ADPCM IMA QuickTime"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_RAD,     sample_fmts_s16,  adpcm_ima_rad,     "ADPCM IMA Radical"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG,  sample_fmts_s16,  adpcm_ima_smjpeg,  "ADPCM IMA Loki SDL MJPEG"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV,     sample_fmts_s16p, adpcm_ima_wav,     "ADPCM IMA WAV"); | ||||
| ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS,      sample_fmts_both, adpcm_ima_ws,      "ADPCM IMA Westwood"); | ||||
|   | ||||
| @@ -437,6 +437,7 @@ void avcodec_register_all(void) | ||||
|     REGISTER_DECODER(ADPCM_IMA_ISS,     adpcm_ima_iss); | ||||
|     REGISTER_DECODER(ADPCM_IMA_OKI,     adpcm_ima_oki); | ||||
|     REGISTER_ENCDEC (ADPCM_IMA_QT,      adpcm_ima_qt); | ||||
|     REGISTER_DECODER(ADPCM_IMA_RAD,     adpcm_ima_rad); | ||||
|     REGISTER_DECODER(ADPCM_IMA_SMJPEG,  adpcm_ima_smjpeg); | ||||
|     REGISTER_ENCDEC (ADPCM_IMA_WAV,     adpcm_ima_wav); | ||||
|     REGISTER_DECODER(ADPCM_IMA_WS,      adpcm_ima_ws); | ||||
|   | ||||
| @@ -363,6 +363,7 @@ enum AVCodecID { | ||||
|     AV_CODEC_ID_ADPCM_AFC  = MKBETAG('A','F','C',' '), | ||||
|     AV_CODEC_ID_ADPCM_IMA_OKI = MKBETAG('O','K','I',' '), | ||||
|     AV_CODEC_ID_ADPCM_DTK  = MKBETAG('D','T','K',' '), | ||||
|     AV_CODEC_ID_ADPCM_IMA_RAD = MKBETAG('R','A','D',' '), | ||||
|  | ||||
|     /* AMR */ | ||||
|     AV_CODEC_ID_AMR_NB = 0x12000, | ||||
|   | ||||
| @@ -1823,6 +1823,13 @@ static const AVCodecDescriptor codec_descriptors[] = { | ||||
|         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube DTK"), | ||||
|         .props     = AV_CODEC_PROP_LOSSY, | ||||
|     }, | ||||
|     { | ||||
|         .id        = AV_CODEC_ID_ADPCM_IMA_RAD, | ||||
|         .type      = AVMEDIA_TYPE_AUDIO, | ||||
|         .name      = "adpcm_ima_rad", | ||||
|         .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Radical"), | ||||
|         .props     = AV_CODEC_PROP_LOSSY, | ||||
|     }, | ||||
|  | ||||
|     /* AMR */ | ||||
|     { | ||||
|   | ||||
| @@ -2883,6 +2883,8 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) | ||||
|                     return blocks * (((ba - 16) * 2 / 3 * 4) / ch); | ||||
|                 case AV_CODEC_ID_ADPCM_IMA_DK4: | ||||
|                     return blocks * (1 + (ba - 4 * ch) * 2 / ch); | ||||
|                 case AV_CODEC_ID_ADPCM_IMA_RAD: | ||||
|                     return blocks * ((ba - 4 * ch) * 2 / ch); | ||||
|                 case AV_CODEC_ID_ADPCM_MS: | ||||
|                     return blocks * (2 + (ba - 7 * ch) * 2 / ch); | ||||
|                 } | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
| #include "libavutil/avutil.h" | ||||
|  | ||||
| #define LIBAVCODEC_VERSION_MAJOR 55 | ||||
| #define LIBAVCODEC_VERSION_MINOR  8 | ||||
| #define LIBAVCODEC_VERSION_MINOR  9 | ||||
| #define LIBAVCODEC_VERSION_MICRO 100 | ||||
|  | ||||
| #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
|  | ||||
| static const AVCodecTag rsd_tags[] = { | ||||
|     { AV_CODEC_ID_ADPCM_THP,       MKTAG('G','A','D','P') }, | ||||
|     { AV_CODEC_ID_ADPCM_IMA_RAD,   MKTAG('R','A','D','P') }, | ||||
|     { AV_CODEC_ID_PCM_S16BE,       MKTAG('P','C','M','B') }, | ||||
|     { AV_CODEC_ID_PCM_S16LE,       MKTAG('P','C','M',' ') }, | ||||
|     { AV_CODEC_ID_NONE, 0 }, | ||||
| @@ -34,7 +35,6 @@ static const AVCodecTag rsd_tags[] = { | ||||
|  | ||||
| static const uint32_t rsd_unsupported_tags[] = { | ||||
|     MKTAG('O','G','G',' '), | ||||
|     MKTAG('R','A','D','P'), | ||||
|     MKTAG('V','A','G',' '), | ||||
|     MKTAG('W','A','D','P'), | ||||
|     MKTAG('X','A','D','P'), | ||||
| @@ -92,6 +92,11 @@ static int rsd_read_header(AVFormatContext *s) | ||||
|     avio_skip(pb, 4); // Unknown | ||||
|  | ||||
|     switch (codec->codec_id) { | ||||
|     case AV_CODEC_ID_ADPCM_IMA_RAD: | ||||
|         codec->block_align = 20 * codec->channels; | ||||
|         if (pb->seekable) | ||||
|             st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); | ||||
|         break; | ||||
|     case AV_CODEC_ID_ADPCM_THP: | ||||
|         /* RSD3GADP is mono, so only alloc enough memory | ||||
|            to store the coeff table for a single channel. */ | ||||
| @@ -131,12 +136,16 @@ static int rsd_read_header(AVFormatContext *s) | ||||
|  | ||||
| static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) | ||||
| { | ||||
|     AVCodecContext *codec = s->streams[0]->codec; | ||||
|     int ret, size = 1024; | ||||
|  | ||||
|     if (url_feof(s->pb)) | ||||
|         return AVERROR_EOF; | ||||
|  | ||||
|     ret = av_get_packet(s->pb, pkt, size); | ||||
|     if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD) | ||||
|         ret = av_get_packet(s->pb, pkt, codec->block_align); | ||||
|     else | ||||
|         ret = av_get_packet(s->pb, pkt, size); | ||||
|  | ||||
|     if (ret != size) { | ||||
|         if (ret < 0) { | ||||
|   | ||||
| @@ -61,6 +61,9 @@ fate-adpcm-ima-iss: CMD = md5 -i $(SAMPLES)/funcom-iss/0004010100.iss -f s16le | ||||
| FATE_ADPCM-$(call DEMDEC, WAV, ADPCM_IMA_OKI) += fate-adpcm-ima-oki | ||||
| fate-adpcm-ima-oki: CMD = md5 -i $(SAMPLES)/oki/test.wav -f s16le | ||||
|  | ||||
| FATE_ADPCM-$(call DEMDEC, RSD, ADPCM_IMA_RAD) += fate-adpcm-ima-rad | ||||
| fate-adpcm-ima-rad: CMD = md5 -i $(SAMPLES)/rsd/hit_run_partial.rsd -f s16le | ||||
|  | ||||
| FATE_ADPCM-$(call DEMDEC, SMJPEG, ADPCM_IMA_SMJPEG) += fate-adpcm-ima-smjpeg | ||||
| fate-adpcm-ima-smjpeg: CMD = framecrc -i $(SAMPLES)/smjpeg/scenwin.mjpg -vn | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								tests/ref/fate/adpcm-ima-rad
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/ref/fate/adpcm-ima-rad
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 495f0ae514c28c6bdcbd40811a17e2a5 | ||||
		Reference in New Issue
	
	Block a user