Xiph CELT/Opus decoder using libcelt.
Signed-off-by: Nicolas George <nicolas.george@normalesup.org>
This commit is contained in:
		
							parent
							
								
									ddb00ad1d8
								
							
						
					
					
						commit
						89451dd6e4
					
				
							
								
								
									
										5
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @ -161,6 +161,7 @@ Configuration options: | |||||||
| External library support: | External library support: | ||||||
|   --enable-avisynth        enable reading of AVISynth script files [no] |   --enable-avisynth        enable reading of AVISynth script files [no] | ||||||
|   --enable-bzlib           enable bzlib [autodetect] |   --enable-bzlib           enable bzlib [autodetect] | ||||||
|  |   --enable-libcelt         enable CELT/Opus decoding via libcelt [no] | ||||||
|   --enable-frei0r          enable frei0r video filtering |   --enable-frei0r          enable frei0r video filtering | ||||||
|   --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] |   --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] | ||||||
|   --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] |   --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] | ||||||
| @ -929,6 +930,7 @@ CONFIG_LIST=" | |||||||
|     h264pred |     h264pred | ||||||
|     hardcoded_tables |     hardcoded_tables | ||||||
|     huffman |     huffman | ||||||
|  |     libcelt | ||||||
|     libdc1394 |     libdc1394 | ||||||
|     libdirac |     libdirac | ||||||
|     libfaac |     libfaac | ||||||
| @ -1393,6 +1395,7 @@ vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" | |||||||
| h264_parser_select="golomb h264dsp h264pred" | h264_parser_select="golomb h264dsp h264pred" | ||||||
| 
 | 
 | ||||||
| # external libraries | # external libraries | ||||||
|  | libcelt_decoder_deps="libcelt" | ||||||
| libdirac_decoder_deps="libdirac !libschroedinger" | libdirac_decoder_deps="libdirac !libschroedinger" | ||||||
| libdirac_encoder_deps="libdirac" | libdirac_encoder_deps="libdirac" | ||||||
| libfaac_encoder_deps="libfaac" | libfaac_encoder_deps="libfaac" | ||||||
| @ -2888,6 +2891,7 @@ check_mathfunc truncf | |||||||
| 
 | 
 | ||||||
| # these are off by default, so fail if requested and not available | # these are off by default, so fail if requested and not available | ||||||
| enabled avisynth   && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32 | enabled avisynth   && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32 | ||||||
|  | enabled libcelt    && require libcelt celt/celt.h celt_decode -lcelt0 | ||||||
| enabled frei0r     && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; } | enabled frei0r     && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; } | ||||||
| enabled libdirac   && require_pkg_config dirac                          \ | enabled libdirac   && require_pkg_config dirac                          \ | ||||||
|     "libdirac_decoder/dirac_parser.h libdirac_encoder/dirac_encoder.h"  \ |     "libdirac_decoder/dirac_parser.h libdirac_encoder/dirac_encoder.h"  \ | ||||||
| @ -3167,6 +3171,7 @@ echo "threading support         ${thread_type-no}" | |||||||
| echo "SDL support               ${sdl-no}" | echo "SDL support               ${sdl-no}" | ||||||
| echo "Sun medialib support      ${mlib-no}" | echo "Sun medialib support      ${mlib-no}" | ||||||
| echo "AVISynth enabled          ${avisynth-no}" | echo "AVISynth enabled          ${avisynth-no}" | ||||||
|  | echo "libcelt enabled           ${libcelt-no}" | ||||||
| echo "frei0r enabled            ${frei0r-no}" | echo "frei0r enabled            ${frei0r-no}" | ||||||
| echo "libdc1394 support         ${libdc1394-no}" | echo "libdc1394 support         ${libdc1394-no}" | ||||||
| echo "libdirac enabled          ${libdirac-no}" | echo "libdirac enabled          ${libdirac-no}" | ||||||
|  | |||||||
| @ -553,6 +553,7 @@ OBJS-$(CONFIG_WEBM_MUXER)              += xiph.o mpeg4audio.o \ | |||||||
|                                           mpegaudiodata.o |                                           mpegaudiodata.o | ||||||
| 
 | 
 | ||||||
| # external codec libraries
 | # external codec libraries
 | ||||||
|  | OBJS-$(CONFIG_LIBCELT_DECODER)            += libcelt_dec.o | ||||||
| OBJS-$(CONFIG_LIBDIRAC_DECODER)           += libdiracdec.o | OBJS-$(CONFIG_LIBDIRAC_DECODER)           += libdiracdec.o | ||||||
| OBJS-$(CONFIG_LIBDIRAC_ENCODER)           += libdiracenc.o libdirac_libschro.o | OBJS-$(CONFIG_LIBDIRAC_ENCODER)           += libdiracenc.o libdirac_libschro.o | ||||||
| OBJS-$(CONFIG_LIBFAAC_ENCODER)            += libfaac.o | OBJS-$(CONFIG_LIBFAAC_ENCODER)            += libfaac.o | ||||||
|  | |||||||
| @ -365,6 +365,7 @@ void avcodec_register_all(void) | |||||||
|     REGISTER_ENCDEC  (XSUB, xsub); |     REGISTER_ENCDEC  (XSUB, xsub); | ||||||
| 
 | 
 | ||||||
|     /* external libraries */ |     /* external libraries */ | ||||||
|  |     REGISTER_DECODER (LIBCELT, libcelt); | ||||||
|     REGISTER_ENCDEC  (LIBDIRAC, libdirac); |     REGISTER_ENCDEC  (LIBDIRAC, libdirac); | ||||||
|     REGISTER_ENCODER (LIBFAAC, libfaac); |     REGISTER_ENCODER (LIBFAAC, libfaac); | ||||||
|     REGISTER_ENCDEC  (LIBGSM, libgsm); |     REGISTER_ENCDEC  (LIBGSM, libgsm); | ||||||
|  | |||||||
							
								
								
									
										134
									
								
								libavcodec/libcelt_dec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								libavcodec/libcelt_dec.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,134 @@ | |||||||
|  | /*
 | ||||||
|  |  * Xiph CELT / Opus decoder using libcelt | ||||||
|  |  * Copyright (c) 2011 Nicolas George | ||||||
|  |  * | ||||||
|  |  * This file is part of FFmpeg. | ||||||
|  |  * | ||||||
|  |  * FFmpeg 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. | ||||||
|  |  * | ||||||
|  |  * FFmpeg 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 FFmpeg; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <celt/celt.h> | ||||||
|  | #include <celt/celt_header.h> | ||||||
|  | #include "avcodec.h" | ||||||
|  | #include "libavutil/intreadwrite.h" | ||||||
|  | 
 | ||||||
|  | struct libcelt_context { | ||||||
|  |     CELTMode *mode; | ||||||
|  |     CELTDecoder *dec; | ||||||
|  |     int frame_bytes; | ||||||
|  |     int discard; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int ff_celt_error_to_averror(int err) | ||||||
|  | { | ||||||
|  |     switch(err) { | ||||||
|  |         case CELT_BAD_ARG:          return AVERROR(EINVAL); | ||||||
|  | #ifdef CELT_BUFFER_TOO_SMALL | ||||||
|  |         case CELT_BUFFER_TOO_SMALL: return AVERROR(ENOBUFS); | ||||||
|  | #endif | ||||||
|  |         case CELT_INTERNAL_ERROR:   return AVERROR(EFAULT); | ||||||
|  |         case CELT_CORRUPTED_DATA:   return AVERROR_INVALIDDATA; | ||||||
|  |         case CELT_UNIMPLEMENTED:    return AVERROR(ENOTSUP); | ||||||
|  |         case CELT_INVALID_STATE:    return AVERROR(ENOTRECOVERABLE); | ||||||
|  |         case CELT_ALLOC_FAIL:       return AVERROR(ENOMEM); | ||||||
|  |         default:                    return AVERROR_UNKNOWN; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int ff_celt_bitstream_version_hack(CELTMode *mode) | ||||||
|  | { | ||||||
|  |     CELTHeader header = { .version_id = 0 }; | ||||||
|  |     celt_header_init(&header, mode, 960, 2); | ||||||
|  |     return header.version_id; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static av_cold int libcelt_dec_init(AVCodecContext *c) | ||||||
|  | { | ||||||
|  |     struct libcelt_context *celt = c->priv_data; | ||||||
|  |     int err; | ||||||
|  | 
 | ||||||
|  |     if (!c->channels || !c->frame_size || | ||||||
|  |         c->frame_size > INT_MAX / sizeof(int16_t) / c->channels) | ||||||
|  |         return AVERROR(EINVAL); | ||||||
|  |     celt->frame_bytes = c->frame_size * c->channels * sizeof(int16_t); | ||||||
|  |     celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err); | ||||||
|  |     if (!celt->mode) | ||||||
|  |         return ff_celt_error_to_averror(err); | ||||||
|  |     celt->dec = celt_decoder_create_custom(celt->mode, c->channels, &err); | ||||||
|  |     if (!celt->dec) { | ||||||
|  |         celt_mode_destroy(celt->mode); | ||||||
|  |         return ff_celt_error_to_averror(err); | ||||||
|  |     } | ||||||
|  |     if (c->extradata_size >= 4) { | ||||||
|  |         celt->discard = AV_RL32(c->extradata); | ||||||
|  |         if (celt->discard < 0 || celt->discard >= c->frame_size) { | ||||||
|  |             av_log(c, AV_LOG_WARNING, | ||||||
|  |                    "Invalid overlap (%d), ignored.\n", celt->discard); | ||||||
|  |             celt->discard = 0; | ||||||
|  |         } | ||||||
|  |         celt->discard *= c->channels * sizeof(int16_t); | ||||||
|  |     } | ||||||
|  |     if(c->extradata_size >= 8) { | ||||||
|  |         unsigned version = AV_RL32(c->extradata + 4); | ||||||
|  |         unsigned lib_version = ff_celt_bitstream_version_hack(celt->mode); | ||||||
|  |         if (version != lib_version) | ||||||
|  |             av_log(c, AV_LOG_WARNING, | ||||||
|  |                    "CELT bitstream version 0x%x may be " | ||||||
|  |                    "improperly decoded by libcelt for version 0x%x.\n", | ||||||
|  |                    version, lib_version); | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static av_cold int libcelt_dec_close(AVCodecContext *c) | ||||||
|  | { | ||||||
|  |     struct libcelt_context *celt = c->priv_data; | ||||||
|  | 
 | ||||||
|  |     celt_decoder_destroy(celt->dec); | ||||||
|  |     celt_mode_destroy(celt->mode); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int libcelt_dec_decode(AVCodecContext *c, void *pcm, int *pcm_size, | ||||||
|  |                               AVPacket *pkt) | ||||||
|  | { | ||||||
|  |     struct libcelt_context *celt = c->priv_data; | ||||||
|  |     int err; | ||||||
|  | 
 | ||||||
|  |     if (*pcm_size < celt->frame_bytes) | ||||||
|  |         return AVERROR(ENOBUFS); | ||||||
|  |     err = celt_decode(celt->dec, pkt->data, pkt->size, pcm, c->frame_size); | ||||||
|  |     if (err < 0) | ||||||
|  |         return ff_celt_error_to_averror(err); | ||||||
|  |     *pcm_size = celt->frame_bytes; | ||||||
|  |     if (celt->discard) { | ||||||
|  |         *pcm_size = celt->frame_bytes - celt->discard; | ||||||
|  |         memmove(pcm, (char *)pcm + celt->discard, *pcm_size); | ||||||
|  |         celt->discard = 0; | ||||||
|  |     } | ||||||
|  |     return pkt->size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AVCodec ff_libcelt_decoder = { | ||||||
|  |     .name           = "libcelt", | ||||||
|  |     .type           = AVMEDIA_TYPE_AUDIO, | ||||||
|  |     .id             = CODEC_ID_CELT, | ||||||
|  |     .priv_data_size = sizeof(struct libcelt_context), | ||||||
|  |     .init           = libcelt_dec_init, | ||||||
|  |     .close          = libcelt_dec_close, | ||||||
|  |     .decode         = libcelt_dec_decode, | ||||||
|  |     .capabilities   = 0, | ||||||
|  |     .long_name = NULL_IF_CONFIG_SMALL("Xiph CELT/Opus decoder using libcelt"), | ||||||
|  | }; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user