FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavcodec
libcelt_dec.c
Go to the documentation of this file.
1
/*
2
* Xiph CELT decoder using libcelt
3
* Copyright (c) 2011 Nicolas George
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include <celt/celt.h>
23
#include <celt/celt_header.h>
24
#include "
avcodec.h
"
25
#include "
internal.h
"
26
#include "
libavutil/intreadwrite.h
"
27
28
struct
libcelt_context
{
29
CELTMode *
mode
;
30
CELTDecoder *
dec
;
31
int
discard
;
32
};
33
34
static
int
ff_celt_error_to_averror
(
int
err)
35
{
36
switch
(err) {
37
case
CELT_BAD_ARG:
return
AVERROR
(EINVAL);
38
#ifdef CELT_BUFFER_TOO_SMALL
39
case
CELT_BUFFER_TOO_SMALL:
return
AVERROR
(ENOBUFS);
40
#endif
41
case
CELT_INTERNAL_ERROR:
return
AVERROR
(EFAULT);
42
case
CELT_CORRUPTED_DATA:
return
AVERROR_INVALIDDATA
;
43
case
CELT_UNIMPLEMENTED:
return
AVERROR
(ENOSYS);
44
#ifdef ENOTRECOVERABLE
45
case
CELT_INVALID_STATE:
return
AVERROR
(ENOTRECOVERABLE);
46
#endif
47
case
CELT_ALLOC_FAIL:
return
AVERROR
(ENOMEM);
48
default
:
return
AVERROR
(EINVAL);
49
}
50
}
51
52
static
int
ff_celt_bitstream_version_hack
(CELTMode *
mode
)
53
{
54
CELTHeader header = { .version_id = 0 };
55
celt_header_init(&header, mode, 960, 2);
56
return
header.version_id;
57
}
58
59
static
av_cold
int
libcelt_dec_init
(
AVCodecContext
*
c
)
60
{
61
struct
libcelt_context
*celt = c->
priv_data
;
62
int
err;
63
64
if
(!c->
channels
|| !c->
frame_size
||
65
c->
frame_size
> INT_MAX /
sizeof
(int16_t) / c->
channels
)
66
return
AVERROR
(EINVAL);
67
celt->
mode
= celt_mode_create(c->
sample_rate
, c->
frame_size
, &err);
68
if
(!celt->
mode
)
69
return
ff_celt_error_to_averror
(err);
70
celt->
dec
= celt_decoder_create_custom(celt->
mode
, c->
channels
, &err);
71
if
(!celt->
dec
) {
72
celt_mode_destroy(celt->
mode
);
73
return
ff_celt_error_to_averror
(err);
74
}
75
if
(c->
extradata_size
>= 4) {
76
celt->
discard
=
AV_RL32
(c->
extradata
);
77
if
(celt->
discard
< 0 || celt->
discard
>= c->
frame_size
) {
78
av_log
(c,
AV_LOG_WARNING
,
79
"Invalid overlap (%d), ignored.\n"
, celt->
discard
);
80
celt->
discard
= 0;
81
}
82
}
83
if
(c->
extradata_size
>= 8) {
84
unsigned
version
=
AV_RL32
(c->
extradata
+ 4);
85
unsigned
lib_version =
ff_celt_bitstream_version_hack
(celt->
mode
);
86
if
(version != lib_version)
87
av_log
(c,
AV_LOG_WARNING
,
88
"CELT bitstream version 0x%x may be "
89
"improperly decoded by libcelt for version 0x%x.\n"
,
90
version, lib_version);
91
}
92
c->
sample_fmt
=
AV_SAMPLE_FMT_S16
;
93
return
0;
94
}
95
96
static
av_cold
int
libcelt_dec_close
(
AVCodecContext
*
c
)
97
{
98
struct
libcelt_context
*celt = c->
priv_data
;
99
100
celt_decoder_destroy(celt->
dec
);
101
celt_mode_destroy(celt->
mode
);
102
return
0;
103
}
104
105
static
int
libcelt_dec_decode
(
AVCodecContext
*
c
,
void
*
data
,
106
int
*got_frame_ptr,
AVPacket
*
pkt
)
107
{
108
struct
libcelt_context
*celt = c->
priv_data
;
109
AVFrame
*
frame
=
data
;
110
int
err;
111
int16_t *pcm;
112
113
frame->
nb_samples
= c->
frame_size
;
114
err =
ff_get_buffer
(c, frame);
115
if
(err < 0) {
116
av_log
(c,
AV_LOG_ERROR
,
"get_buffer() failed\n"
);
117
return
err;
118
}
119
pcm = (int16_t *)frame->
data
[0];
120
err = celt_decode(celt->
dec
, pkt->
data
, pkt->
size
, pcm, c->
frame_size
);
121
if
(err < 0)
122
return
ff_celt_error_to_averror
(err);
123
if
(celt->
discard
) {
124
frame->
nb_samples
-= celt->
discard
;
125
memmove(pcm, pcm + celt->
discard
* c->
channels
,
126
frame->
nb_samples
* c->
channels
*
sizeof
(int16_t));
127
celt->
discard
= 0;
128
}
129
*got_frame_ptr = 1;
130
return
pkt->
size
;
131
}
132
133
AVCodec
ff_libcelt_decoder
= {
134
.
name
=
"libcelt"
,
135
.type =
AVMEDIA_TYPE_AUDIO
,
136
.id =
AV_CODEC_ID_CELT
,
137
.priv_data_size =
sizeof
(
struct
libcelt_context
),
138
.init =
libcelt_dec_init
,
139
.close =
libcelt_dec_close
,
140
.decode =
libcelt_dec_decode
,
141
.capabilities =
CODEC_CAP_DR1
,
142
.long_name =
NULL_IF_CONFIG_SMALL
(
"Xiph CELT decoder using libcelt"
),
143
};
Generated on Sat May 25 2013 04:01:06 for FFmpeg by
1.8.2