mirror of
				https://git.ffmpeg.org/ffmpeg.git
				synced 2025-10-30 23:30:55 +00:00 
			
		
		
		
	Port SMPTE S302M audio decoder from FFmbc 0.3.
This commit is contained in:
		
							parent
							
								
									b44c8ad280
								
							
						
					
					
						commit
						9aa91043f3
					
				
					 7 changed files with 147 additions and 0 deletions
				
			
		|  | @ -7,6 +7,7 @@ version <next>: | ||||||
| - Lots of deprecated API cruft removed | - Lots of deprecated API cruft removed | ||||||
| - fft and imdct optimizations for AVX (Sandy Bridge) processors | - fft and imdct optimizations for AVX (Sandy Bridge) processors | ||||||
| - DPX image encoder | - DPX image encoder | ||||||
|  | - SMPTE 302M AES3 audio decoder | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| version 0.7_beta1: | version 0.7_beta1: | ||||||
|  |  | ||||||
|  | @ -673,6 +673,7 @@ following image formats are supported: | ||||||
| @item Sierra VMD audio       @tab     @tab  X | @item Sierra VMD audio       @tab     @tab  X | ||||||
|     @tab Used in Sierra VMD files. |     @tab Used in Sierra VMD files. | ||||||
| @item Smacker audio          @tab     @tab  X | @item Smacker audio          @tab     @tab  X | ||||||
|  | @item SMPTE 302M AES3 audio  @tab     @tab  X | ||||||
| @item Speex                  @tab     @tab  E | @item Speex                  @tab     @tab  E | ||||||
|     @tab supported through external library libspeex |     @tab supported through external library libspeex | ||||||
| @item True Audio (TTA)       @tab     @tab  X | @item True Audio (TTA)       @tab     @tab  X | ||||||
|  |  | ||||||
|  | @ -324,6 +324,7 @@ OBJS-$(CONFIG_RV30_DECODER)            += rv30.o rv34.o rv30dsp.o        \ | ||||||
|                                           mpegvideo.o error_resilience.o |                                           mpegvideo.o error_resilience.o | ||||||
| OBJS-$(CONFIG_RV40_DECODER)            += rv40.o rv34.o rv40dsp.o        \
 | OBJS-$(CONFIG_RV40_DECODER)            += rv40.o rv34.o rv40dsp.o        \
 | ||||||
|                                           mpegvideo.o error_resilience.o |                                           mpegvideo.o error_resilience.o | ||||||
|  | OBJS-$(CONFIG_S302M_DECODER)           += s302m.o | ||||||
| OBJS-$(CONFIG_SGI_DECODER)             += sgidec.o | OBJS-$(CONFIG_SGI_DECODER)             += sgidec.o | ||||||
| OBJS-$(CONFIG_SGI_ENCODER)             += sgienc.o rle.o | OBJS-$(CONFIG_SGI_ENCODER)             += sgienc.o rle.o | ||||||
| OBJS-$(CONFIG_SHORTEN_DECODER)         += shorten.o | OBJS-$(CONFIG_SHORTEN_DECODER)         += shorten.o | ||||||
|  |  | ||||||
|  | @ -177,6 +177,7 @@ void avcodec_register_all(void) | ||||||
|     REGISTER_ENCDEC  (RV20, rv20); |     REGISTER_ENCDEC  (RV20, rv20); | ||||||
|     REGISTER_DECODER (RV30, rv30); |     REGISTER_DECODER (RV30, rv30); | ||||||
|     REGISTER_DECODER (RV40, rv40); |     REGISTER_DECODER (RV40, rv40); | ||||||
|  |     REGISTER_DECODER (S302M, s302m); | ||||||
|     REGISTER_ENCDEC  (SGI, sgi); |     REGISTER_ENCDEC  (SGI, sgi); | ||||||
|     REGISTER_DECODER (SMACKER, smacker); |     REGISTER_DECODER (SMACKER, smacker); | ||||||
|     REGISTER_DECODER (SMC, smc); |     REGISTER_DECODER (SMC, smc); | ||||||
|  |  | ||||||
|  | @ -232,6 +232,7 @@ enum CodecID { | ||||||
|     CODEC_ID_PCM_F64LE, |     CODEC_ID_PCM_F64LE, | ||||||
|     CODEC_ID_PCM_BLURAY, |     CODEC_ID_PCM_BLURAY, | ||||||
|     CODEC_ID_PCM_LXF, |     CODEC_ID_PCM_LXF, | ||||||
|  |     CODEC_ID_S302M, | ||||||
| 
 | 
 | ||||||
|     /* various ADPCM codecs */ |     /* various ADPCM codecs */ | ||||||
|     CODEC_ID_ADPCM_IMA_QT= 0x11000, |     CODEC_ID_ADPCM_IMA_QT= 0x11000, | ||||||
|  |  | ||||||
							
								
								
									
										141
									
								
								libavcodec/s302m.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								libavcodec/s302m.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,141 @@ | ||||||
|  | /*
 | ||||||
|  |  * SMPTE 302M decoder | ||||||
|  |  * Copyright (c) 2008 Laurent Aimar <fenrir@videolan.org> | ||||||
|  |  * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com> | ||||||
|  |  * | ||||||
|  |  * This file is part of Libav. | ||||||
|  |  * | ||||||
|  |  * Libav is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * Libav is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with Libav; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "libavutil/intreadwrite.h" | ||||||
|  | #include "avcodec.h" | ||||||
|  | 
 | ||||||
|  | #define AES3_HEADER_LEN 4 | ||||||
|  | 
 | ||||||
|  | static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, | ||||||
|  |                                     int buf_size) | ||||||
|  | { | ||||||
|  |     uint32_t h; | ||||||
|  |     int frame_size, channels, id, bits; | ||||||
|  | 
 | ||||||
|  |     if (buf_size <= AES3_HEADER_LEN) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "frame is too short\n"); | ||||||
|  |         return AVERROR_INVALIDDATA; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |      * AES3 header : | ||||||
|  |      * size:            16 | ||||||
|  |      * number channels   2 | ||||||
|  |      * channel_id        8 | ||||||
|  |      * bits per samples  2 | ||||||
|  |      * alignments        4 | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     h = AV_RB32(buf); | ||||||
|  |     frame_size =  (h >> 16) & 0xffff; | ||||||
|  |     channels   = ((h >> 14) & 0x0003) * 2 +  2; | ||||||
|  |     id         =  (h >>  6) & 0x00ff; | ||||||
|  |     bits       = ((h >>  4) & 0x0003) * 4 + 16; | ||||||
|  | 
 | ||||||
|  |     if (AES3_HEADER_LEN + frame_size != buf_size || bits > 24) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "frame has invalid header\n"); | ||||||
|  |         return AVERROR_INVALIDDATA; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Set output properties */ | ||||||
|  |     avctx->bits_per_coded_sample = bits; | ||||||
|  |     if (bits > 16) | ||||||
|  |         avctx->sample_fmt = SAMPLE_FMT_S32; | ||||||
|  |     else | ||||||
|  |         avctx->sample_fmt = SAMPLE_FMT_S16; | ||||||
|  | 
 | ||||||
|  |     avctx->channels    = channels; | ||||||
|  |     avctx->sample_rate = 48000; | ||||||
|  |     avctx->bit_rate    = 48000 * avctx->channels * (avctx->bits_per_coded_sample + 4) + | ||||||
|  |                          32 * (48000 / (buf_size * 8 / | ||||||
|  |                                         (avctx->channels * | ||||||
|  |                                          (avctx->bits_per_coded_sample + 4)))); | ||||||
|  | 
 | ||||||
|  |     return frame_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int s302m_decode_frame(AVCodecContext *avctx, void *data, | ||||||
|  |                               int *data_size, AVPacket *avpkt) | ||||||
|  | { | ||||||
|  |     const uint8_t *buf = avpkt->data; | ||||||
|  |     int buf_size       = avpkt->size; | ||||||
|  | 
 | ||||||
|  |     int frame_size = s302m_parse_frame_header(avctx, buf, buf_size); | ||||||
|  |     if (frame_size < 0) | ||||||
|  |         return frame_size; | ||||||
|  | 
 | ||||||
|  |     buf_size -= AES3_HEADER_LEN; | ||||||
|  |     buf      += AES3_HEADER_LEN; | ||||||
|  | 
 | ||||||
|  |     if (*data_size < 4 * buf_size * 8 / (avctx->bits_per_coded_sample + 4)) | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|  |     if (avctx->bits_per_coded_sample == 24) { | ||||||
|  |         uint32_t *o = data; | ||||||
|  |         for (; buf_size > 6; buf_size -= 7) { | ||||||
|  |             *o++ = (av_reverse[buf[2]]        << 24) | | ||||||
|  |                    (av_reverse[buf[1]]        << 16) | | ||||||
|  |                    (av_reverse[buf[0]]        <<  8); | ||||||
|  |             *o++ = (av_reverse[buf[6] & 0xf0] << 28) | | ||||||
|  |                    (av_reverse[buf[5]]        << 20) | | ||||||
|  |                    (av_reverse[buf[4]]        << 12) | | ||||||
|  |                    (av_reverse[buf[3] & 0x0f] <<  8); | ||||||
|  |             buf += 7; | ||||||
|  |         } | ||||||
|  |         *data_size = (uint8_t*) o - (uint8_t*) data; | ||||||
|  |     } else if (avctx->bits_per_coded_sample == 20) { | ||||||
|  |         uint32_t *o = data; | ||||||
|  |         for (; buf_size > 5; buf_size -= 6) { | ||||||
|  |             *o++ = (av_reverse[buf[2] & 0xf0] << 28) | | ||||||
|  |                    (av_reverse[buf[1]]        << 20) | | ||||||
|  |                    (av_reverse[buf[0]]        << 12); | ||||||
|  |             *o++ = (av_reverse[buf[5] & 0xf0] << 28) | | ||||||
|  |                    (av_reverse[buf[4]]        << 20) | | ||||||
|  |                    (av_reverse[buf[3]]        << 12); | ||||||
|  |             buf += 6; | ||||||
|  |         } | ||||||
|  |         *data_size = (uint8_t*) o - (uint8_t*) data; | ||||||
|  |     } else { | ||||||
|  |         uint16_t *o = data; | ||||||
|  |         for (; buf_size > 4; buf_size -= 5) { | ||||||
|  |             *o++ = (av_reverse[buf[1]]        <<  8) | | ||||||
|  |                     av_reverse[buf[0]]; | ||||||
|  |             *o++ = (av_reverse[buf[4] & 0xf0] << 12) | | ||||||
|  |                    (av_reverse[buf[3]]        <<  4) | | ||||||
|  |                     av_reverse[buf[2] & 0x0f]; | ||||||
|  |             buf += 5; | ||||||
|  |         } | ||||||
|  |         *data_size = (uint8_t*) o - (uint8_t*) data; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return buf - avpkt->data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | AVCodec ff_s302m_decoder = { | ||||||
|  |     .name           = "s302m", | ||||||
|  |     .type           = AVMEDIA_TYPE_AUDIO, | ||||||
|  |     .id             = CODEC_ID_S302M, | ||||||
|  |     .priv_data_size = 0, | ||||||
|  |     .decode         = s302m_decode_frame, | ||||||
|  |     .long_name      = NULL_IF_CONFIG_SMALL("SMPTE 302M"), | ||||||
|  | }; | ||||||
|  | @ -524,6 +524,7 @@ static const StreamType MISC_types[] = { | ||||||
| static const StreamType REGD_types[] = { | static const StreamType REGD_types[] = { | ||||||
|     { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, CODEC_ID_DIRAC }, |     { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, CODEC_ID_DIRAC }, | ||||||
|     { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO,   CODEC_ID_AC3 }, |     { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO,   CODEC_ID_AC3 }, | ||||||
|  |     { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, CODEC_ID_S302M }, | ||||||
|     { 0 }, |     { 0 }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Baptiste Coudurier
						Baptiste Coudurier