Skip to content

Commit 9886085

Browse files
author
Romain Beauxis
committed
Add optional offset/length in swresample.
1 parent a514383 commit 9886085

File tree

3 files changed

+77
-26
lines changed

3 files changed

+77
-26
lines changed

swresample/swresample.ml

+3-1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ module Make (I : AudioData) (O : AudioData) = struct
323323
~out_sample_format:(Avcodec.Audio.get_sample_format out_codec)
324324
(Avcodec.Audio.get_sample_rate out_codec)
325325

326-
external convert : t -> I.t -> O.t = "ocaml_swresample_convert"
326+
external convert : ?offset:int -> ?length:int -> t -> I.t -> O.t
327+
= "ocaml_swresample_convert"
328+
327329
external flush : t -> O.t = "ocaml_swresample_flush"
328330
end

swresample/swresample.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ module Make (I : AudioData) (O : AudioData) : sig
8080
format.
8181
8282
Raise Error if the conversion failed. *)
83-
val convert : t -> I.t -> O.t
83+
val convert : ?offset:int -> ?length:int -> t -> I.t -> O.t
8484

8585
(** [Swresample.convert rpsp] flushes the last remaining data. *)
8686
val flush : t -> O.t

swresample/swresample_stubs.c

+73-24
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct swr_t {
4646
value out_vector;
4747
int out_vector_nb_samples;
4848

49-
int (*get_in_samples)(swr_t *, value *);
49+
int (*get_in_samples)(swr_t *, value *, int);
5050
void (*convert)(swr_t *, int, int);
5151
};
5252

@@ -73,7 +73,7 @@ static void alloc_data(struct audio_t *audio, int nb_samples) {
7373
audio->nb_samples = nb_samples;
7474
}
7575

76-
static int get_in_samples_frame(swr_t *swr, value *in_vector) {
76+
static int get_in_samples_frame(swr_t *swr, value *in_vector, int offset) {
7777
AVFrame *frame = Frame_val(*in_vector);
7878
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 0, 100)
7979
caml_release_runtime_system();
@@ -83,6 +83,9 @@ static int get_in_samples_frame(swr_t *swr, value *in_vector) {
8383
int nb_channels = frame->channels;
8484
#endif
8585

86+
if (offset != 0)
87+
Fail("Cannot use offset with frame data!");
88+
8689
if (nb_channels != swr->in.nb_channels)
8790
Fail("Swresample failed to convert %d channels : %d channels were expected",
8891
nb_channels, swr->in.nb_channels);
@@ -98,61 +101,82 @@ static int get_in_samples_frame(swr_t *swr, value *in_vector) {
98101
return frame->nb_samples;
99102
}
100103

101-
static int get_in_samples_string(swr_t *swr, value *in_vector) {
104+
static int get_in_samples_string(swr_t *swr, value *in_vector, int offset) {
102105
int str_len = caml_string_length(*in_vector);
103-
int nb_samples = str_len / (swr->in.bytes_per_samples * swr->in.nb_channels);
106+
int bytes_per_sample = swr->in.bytes_per_samples * swr->in.nb_channels;
107+
int nb_samples = str_len / bytes_per_sample - offset;
108+
109+
if (nb_samples < 0)
110+
Fail("Invalid offset!");
104111

105112
if (nb_samples > swr->in.nb_samples)
106113
alloc_data(&swr->in, nb_samples);
107114

108-
memcpy(swr->in.data[0], (uint8_t *)String_val(*in_vector), str_len);
115+
memcpy(swr->in.data[0],
116+
(uint8_t *)String_val(*in_vector) + offset * bytes_per_sample,
117+
str_len);
109118

110119
return nb_samples;
111120
}
112121

113-
static int get_in_samples_planar_string(swr_t *swr, value *in_vector) {
122+
static int get_in_samples_planar_string(swr_t *swr, value *in_vector,
123+
int offset) {
114124
CAMLparam0();
115125
CAMLlocal1(str);
116126
int str_len = caml_string_length(Field(*in_vector, 0));
117-
int i, nb_samples = str_len / swr->in.bytes_per_samples;
127+
int i;
128+
int nb_samples = str_len / swr->in.bytes_per_samples - offset;
129+
130+
if (nb_samples < 0)
131+
Fail("Invalid offset!");
118132

119133
if (nb_samples > swr->in.nb_samples)
120134
alloc_data(&swr->in, nb_samples);
121135

122136
for (i = 0; i < swr->in.nb_channels; i++) {
123137
str = Field(*in_vector, i);
124138

125-
if (str_len != caml_string_length(str))
139+
if (str_len != caml_string_length(str) - offset * swr->in.bytes_per_samples)
126140
Fail("Swresample failed to convert channel %d's %lu bytes : %d bytes "
127141
"were expected",
128142
i, caml_string_length(str), str_len);
129143

130-
memcpy(swr->in.data[i], (uint8_t *)String_val(str), str_len);
144+
memcpy(swr->in.data[i],
145+
(uint8_t *)String_val(str) + offset * swr->in.bytes_per_samples,
146+
str_len);
131147
}
132148
CAMLreturnT(int, nb_samples);
133149
}
134150

135-
static int get_in_samples_float_array(swr_t *swr, value *in_vector) {
151+
static int get_in_samples_float_array(swr_t *swr, value *in_vector,
152+
int offset) {
136153
int i, linesize = Wosize_val(*in_vector) / Double_wosize;
137-
int nb_samples = linesize / swr->in.nb_channels;
154+
int nb_samples = linesize / swr->in.nb_channels - offset;
155+
156+
if (nb_samples < 0)
157+
Fail("Invalid offset!");
138158

139159
if (nb_samples > swr->in.nb_samples)
140160
alloc_data(&swr->in, nb_samples);
141161

142162
double *pcm = (double *)swr->in.data[0];
143163

144164
for (i = 0; i < linesize; i++) {
145-
pcm[i] = Double_field(*in_vector, i);
165+
pcm[i] = Double_field(*in_vector, i + offset);
146166
}
147167

148168
return nb_samples;
149169
}
150170

151-
static int get_in_samples_planar_float_array(swr_t *swr, value *in_vector) {
171+
static int get_in_samples_planar_float_array(swr_t *swr, value *in_vector,
172+
int offset) {
152173
CAMLparam0();
153174
CAMLlocal1(fa);
154175
int i, j, nb_words = Wosize_val(Field(*in_vector, 0));
155-
int nb_samples = nb_words / Double_wosize;
176+
int nb_samples = nb_words / Double_wosize - offset;
177+
178+
if (nb_samples < 0)
179+
Fail("Invalid offset!");
156180

157181
if (nb_samples > swr->in.nb_samples)
158182
alloc_data(&swr->in, nb_samples);
@@ -168,21 +192,32 @@ static int get_in_samples_planar_float_array(swr_t *swr, value *in_vector) {
168192
double *pcm = (double *)swr->in.data[i];
169193

170194
for (j = 0; j < nb_samples; j++) {
171-
pcm[j] = Double_field(fa, j);
195+
pcm[j] = Double_field(fa, j + offset);
172196
}
173197
}
174198
CAMLreturnT(int, nb_samples);
175199
}
176200

177-
static int get_in_samples_ba(swr_t *swr, value *in_vector) {
178-
swr->in.data[0] = Caml_ba_data_val(*in_vector);
179-
return Caml_ba_array_val(*in_vector)->dim[0] / swr->in.nb_channels;
201+
static int get_in_samples_ba(swr_t *swr, value *in_vector, int offset) {
202+
CAMLparam0();
203+
CAMLlocal1(ba);
204+
int nb_samples =
205+
Caml_ba_array_val(*in_vector)->dim[0] / swr->in.nb_channels - offset;
206+
207+
if (nb_samples < 0)
208+
Fail("Invalid offset!");
209+
210+
swr->in.data[0] = Caml_ba_data_val(*in_vector) + offset * swr->in.nb_channels;
211+
CAMLreturnT(int, nb_samples);
180212
}
181213

182-
static int get_in_samples_planar_ba(swr_t *swr, value *in_vector) {
214+
static int get_in_samples_planar_ba(swr_t *swr, value *in_vector, int offset) {
183215
CAMLparam0();
184216
CAMLlocal1(ba);
185-
int nb_samples = Caml_ba_array_val(Field(*in_vector, 0))->dim[0];
217+
int nb_samples = Caml_ba_array_val(Field(*in_vector, 0))->dim[0] - offset;
218+
219+
if (nb_samples < 0)
220+
Fail("Invalid offset!");
186221

187222
for (int i = 0; i < swr->in.nb_channels; i++) {
188223
ba = Field(*in_vector, i);
@@ -192,7 +227,7 @@ static int get_in_samples_planar_ba(swr_t *swr, value *in_vector) {
192227
"were expected",
193228
i, Caml_ba_array_val(ba)->dim[0], nb_samples);
194229

195-
swr->in.data[i] = Caml_ba_data_val(ba);
230+
swr->in.data[i] = Caml_ba_data_val(ba) + offset;
196231
}
197232
CAMLreturnT(int, nb_samples);
198233
}
@@ -415,8 +450,9 @@ static void convert_to_planar_ba(swr_t *swr, int in_nb_samples,
415450
}
416451
}
417452

418-
CAMLprim value ocaml_swresample_convert(value _swr, value _in_vector) {
419-
CAMLparam2(_swr, _in_vector);
453+
CAMLprim value ocaml_swresample_convert(value _ofs, value _len, value _swr,
454+
value _in_vector) {
455+
CAMLparam4(_ofs, _len, _swr, _in_vector);
420456
swr_t *swr = Swr_val(_swr);
421457

422458
// consistency check between the input channels and the context ones
@@ -434,10 +470,23 @@ CAMLprim value ocaml_swresample_convert(value _swr, value _in_vector) {
434470

435471
// acquisition of the input samples and the input number of samples per
436472
// channel
437-
int in_nb_samples = swr->get_in_samples(swr, &_in_vector);
473+
int offset = 0;
474+
if (_ofs != Val_none) {
475+
offset = Int_val(Field(_ofs, 0));
476+
}
477+
478+
int in_nb_samples = swr->get_in_samples(swr, &_in_vector, offset);
438479
if (in_nb_samples < 0)
439480
ocaml_avutil_raise_error(in_nb_samples);
440481

482+
if (_len != Val_none) {
483+
int asked_nb_samples = Int_val(Field(_len, 0));
484+
if (in_nb_samples < asked_nb_samples) {
485+
Fail("Input vector too small!");
486+
}
487+
in_nb_samples = asked_nb_samples;
488+
}
489+
441490
// Computation of the output number of samples per channel according to the
442491
// input ones
443492
int out_nb_samples = swr_get_out_samples(swr->context, in_nb_samples);

0 commit comments

Comments
 (0)