Original fix by Michael Niedermayer.
Slightly modified to avoid the now redundant multiplications
and divisions in the main code path.
... | ... |
@@ -27,7 +27,7 @@ |
27 | 27 |
struct libcelt_context { |
28 | 28 |
CELTMode *mode; |
29 | 29 |
CELTDecoder *dec; |
30 |
- int frame_bytes; |
|
30 |
+ AVFrame frame; |
|
31 | 31 |
int discard; |
32 | 32 |
}; |
33 | 33 |
|
... | ... |
@@ -64,7 +64,6 @@ static av_cold int libcelt_dec_init(AVCodecContext *c) |
64 | 64 |
if (!c->channels || !c->frame_size || |
65 | 65 |
c->frame_size > INT_MAX / sizeof(int16_t) / c->channels) |
66 | 66 |
return AVERROR(EINVAL); |
67 |
- celt->frame_bytes = c->frame_size * c->channels * sizeof(int16_t); |
|
68 | 67 |
celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err); |
69 | 68 |
if (!celt->mode) |
70 | 69 |
return ff_celt_error_to_averror(err); |
... | ... |
@@ -80,7 +79,6 @@ static av_cold int libcelt_dec_init(AVCodecContext *c) |
80 | 80 |
"Invalid overlap (%d), ignored.\n", celt->discard); |
81 | 81 |
celt->discard = 0; |
82 | 82 |
} |
83 |
- celt->discard *= c->channels * sizeof(int16_t); |
|
84 | 83 |
} |
85 | 84 |
if (c->extradata_size >= 8) { |
86 | 85 |
unsigned version = AV_RL32(c->extradata + 4); |
... | ... |
@@ -92,6 +90,8 @@ static av_cold int libcelt_dec_init(AVCodecContext *c) |
92 | 92 |
version, lib_version); |
93 | 93 |
} |
94 | 94 |
c->sample_fmt = AV_SAMPLE_FMT_S16; |
95 |
+ avcodec_get_frame_defaults(&celt->frame); |
|
96 |
+ c->coded_frame = &celt->frame; |
|
95 | 97 |
return 0; |
96 | 98 |
} |
97 | 99 |
|
... | ... |
@@ -104,23 +104,31 @@ static av_cold int libcelt_dec_close(AVCodecContext *c) |
104 | 104 |
return 0; |
105 | 105 |
} |
106 | 106 |
|
107 |
-static int libcelt_dec_decode(AVCodecContext *c, void *pcm, int *pcm_size, |
|
108 |
- AVPacket *pkt) |
|
107 |
+static int libcelt_dec_decode(AVCodecContext *c, void *frame, |
|
108 |
+ int *got_frame_ptr, AVPacket *pkt) |
|
109 | 109 |
{ |
110 | 110 |
struct libcelt_context *celt = c->priv_data; |
111 | 111 |
int err; |
112 |
+ int16_t *pcm; |
|
112 | 113 |
|
113 |
- if (*pcm_size < celt->frame_bytes) |
|
114 |
- return AVERROR(ENOBUFS); |
|
114 |
+ celt->frame.nb_samples = c->frame_size; |
|
115 |
+ err = c->get_buffer(c, &celt->frame); |
|
116 |
+ if (err < 0) { |
|
117 |
+ av_log(c, AV_LOG_ERROR, "get_buffer() failed\n"); |
|
118 |
+ return err; |
|
119 |
+ } |
|
120 |
+ pcm = (int16_t *)celt->frame.data[0]; |
|
115 | 121 |
err = celt_decode(celt->dec, pkt->data, pkt->size, pcm, c->frame_size); |
116 | 122 |
if (err < 0) |
117 | 123 |
return ff_celt_error_to_averror(err); |
118 |
- *pcm_size = celt->frame_bytes; |
|
119 | 124 |
if (celt->discard) { |
120 |
- *pcm_size = celt->frame_bytes - celt->discard; |
|
121 |
- memmove(pcm, (char *)pcm + celt->discard, *pcm_size); |
|
125 |
+ celt->frame.nb_samples -= celt->discard; |
|
126 |
+ memmove(pcm, pcm + celt->discard * c->channels, |
|
127 |
+ celt->frame.nb_samples * c->channels * sizeof(int16_t)); |
|
122 | 128 |
celt->discard = 0; |
123 | 129 |
} |
130 |
+ *got_frame_ptr = 1; |
|
131 |
+ *(AVFrame *)frame = celt->frame; |
|
124 | 132 |
return pkt->size; |
125 | 133 |
} |
126 | 134 |
|
... | ... |
@@ -132,6 +140,6 @@ AVCodec ff_libcelt_decoder = { |
132 | 132 |
.init = libcelt_dec_init, |
133 | 133 |
.close = libcelt_dec_close, |
134 | 134 |
.decode = libcelt_dec_decode, |
135 |
- .capabilities = 0, |
|
135 |
+ .capabilities = CODEC_CAP_DR1, |
|
136 | 136 |
.long_name = NULL_IF_CONFIG_SMALL("Xiph CELT decoder using libcelt"), |
137 | 137 |
}; |