| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SMPTE 302M decoder | 
					
						
							|  |  |  |  * Copyright (c) 2008 Laurent Aimar <fenrir@videolan.org> | 
					
						
							|  |  |  |  * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-05-12 04:51:24 +02:00
										 |  |  |  * This file is part of FFmpeg. | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-05-12 04:51:24 +02:00
										 |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-05-12 04:51:24 +02:00
										 |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2011-05-12 04:51:24 +02:00
										 |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "libavutil/intreadwrite.h"
 | 
					
						
							|  |  |  | #include "avcodec.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define AES3_HEADER_LEN 4
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  | typedef struct S302MDecodeContext { | 
					
						
							|  |  |  |     AVFrame frame; | 
					
						
							|  |  |  | } S302MDecodeContext; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, | 
					
						
							|  |  |  |                                     int buf_size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t h; | 
					
						
							| 
									
										
										
										
											2011-06-01 17:26:27 +01:00
										 |  |  |     int frame_size, channels, bits; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |     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) | 
					
						
							| 
									
										
										
										
											2011-07-29 02:36:11 -04:00
										 |  |  |         avctx->sample_fmt = AV_SAMPLE_FMT_S32; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2011-07-29 02:36:11 -04:00
										 |  |  |         avctx->sample_fmt = AV_SAMPLE_FMT_S16; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     avctx->channels    = channels; | 
					
						
							| 
									
										
										
										
											2011-05-13 00:23:00 +02:00
										 |  |  |     switch(channels) { | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |             avctx->channel_layout = AV_CH_LAYOUT_STEREO; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 4: | 
					
						
							|  |  |  |             avctx->channel_layout = AV_CH_LAYOUT_QUAD; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2012-04-05 21:43:18 -07:00
										 |  |  |         case 6: | 
					
						
							|  |  |  |             avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2011-05-13 00:23:00 +02:00
										 |  |  |         case 8: | 
					
						
							|  |  |  |             avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK | AV_CH_LAYOUT_STEREO_DOWNMIX; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |     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, | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |                               int *got_frame_ptr, AVPacket *avpkt) | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     S302MDecodeContext *s = avctx->priv_data; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |     const uint8_t *buf = avpkt->data; | 
					
						
							|  |  |  |     int buf_size       = avpkt->size; | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     int block_size, ret; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     /* get output buffer */ | 
					
						
							|  |  |  |     block_size = (avctx->bits_per_coded_sample + 4) / 4; | 
					
						
							|  |  |  |     s->frame.nb_samples = 2 * (buf_size / block_size) / avctx->channels; | 
					
						
							|  |  |  |     if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buf_size = (s->frame.nb_samples * avctx->channels / 2) * block_size; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (avctx->bits_per_coded_sample == 24) { | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |         uint32_t *o = (uint32_t *)s->frame.data[0]; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |         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) | | 
					
						
							| 
									
										
										
										
											2011-06-04 14:36:30 +02:00
										 |  |  |                    (av_reverse[buf[3] & 0x0f] <<  4); | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |             buf += 7; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (avctx->bits_per_coded_sample == 20) { | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |         uint32_t *o = (uint32_t *)s->frame.data[0]; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |         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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |         uint16_t *o = (uint16_t *)s->frame.data[0]; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |         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) | | 
					
						
							| 
									
										
										
										
											2011-06-04 14:36:30 +02:00
										 |  |  |                    (av_reverse[buf[2]]        >>  4); | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |             buf += 5; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     *got_frame_ptr   = 1; | 
					
						
							|  |  |  |     *(AVFrame *)data = s->frame; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return avpkt->size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int s302m_decode_init(AVCodecContext *avctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     S302MDecodeContext *s = avctx->priv_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     avcodec_get_frame_defaults(&s->frame); | 
					
						
							|  |  |  |     avctx->coded_frame = &s->frame; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AVCodec ff_s302m_decoder = { | 
					
						
							|  |  |  |     .name           = "s302m", | 
					
						
							|  |  |  |     .type           = AVMEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |     .id             = CODEC_ID_S302M, | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     .priv_data_size = sizeof(S302MDecodeContext), | 
					
						
							|  |  |  |     .init           = s302m_decode_init, | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |     .decode         = s302m_decode_frame, | 
					
						
							| 
									
										
										
										
											2011-09-06 12:17:45 -04:00
										 |  |  |     .capabilities   = CODEC_CAP_DR1, | 
					
						
							| 
									
										
										
										
											2011-04-12 15:29:09 -07:00
										 |  |  |     .long_name      = NULL_IF_CONFIG_SMALL("SMPTE 302M"), | 
					
						
							|  |  |  | }; |