@@ -46,7 +46,7 @@ struct swr_t {
46
46
value out_vector ;
47
47
int out_vector_nb_samples ;
48
48
49
- int (* get_in_samples )(swr_t * , value * );
49
+ int (* get_in_samples )(swr_t * , value * , int );
50
50
void (* convert )(swr_t * , int , int );
51
51
};
52
52
@@ -73,7 +73,7 @@ static void alloc_data(struct audio_t *audio, int nb_samples) {
73
73
audio -> nb_samples = nb_samples ;
74
74
}
75
75
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 ) {
77
77
AVFrame * frame = Frame_val (* in_vector );
78
78
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT (56 , 0 , 100 )
79
79
caml_release_runtime_system ();
@@ -83,6 +83,9 @@ static int get_in_samples_frame(swr_t *swr, value *in_vector) {
83
83
int nb_channels = frame -> channels ;
84
84
#endif
85
85
86
+ if (offset != 0 )
87
+ Fail ("Cannot use offset with frame data!" );
88
+
86
89
if (nb_channels != swr -> in .nb_channels )
87
90
Fail ("Swresample failed to convert %d channels : %d channels were expected" ,
88
91
nb_channels , swr -> in .nb_channels );
@@ -98,61 +101,82 @@ static int get_in_samples_frame(swr_t *swr, value *in_vector) {
98
101
return frame -> nb_samples ;
99
102
}
100
103
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 ) {
102
105
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!" );
104
111
105
112
if (nb_samples > swr -> in .nb_samples )
106
113
alloc_data (& swr -> in , nb_samples );
107
114
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 );
109
118
110
119
return nb_samples ;
111
120
}
112
121
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 ) {
114
124
CAMLparam0 ();
115
125
CAMLlocal1 (str );
116
126
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!" );
118
132
119
133
if (nb_samples > swr -> in .nb_samples )
120
134
alloc_data (& swr -> in , nb_samples );
121
135
122
136
for (i = 0 ; i < swr -> in .nb_channels ; i ++ ) {
123
137
str = Field (* in_vector , i );
124
138
125
- if (str_len != caml_string_length (str ))
139
+ if (str_len != caml_string_length (str ) - offset * swr -> in . bytes_per_samples )
126
140
Fail ("Swresample failed to convert channel %d's %lu bytes : %d bytes "
127
141
"were expected" ,
128
142
i , caml_string_length (str ), str_len );
129
143
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 );
131
147
}
132
148
CAMLreturnT (int , nb_samples );
133
149
}
134
150
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 ) {
136
153
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!" );
138
158
139
159
if (nb_samples > swr -> in .nb_samples )
140
160
alloc_data (& swr -> in , nb_samples );
141
161
142
162
double * pcm = (double * )swr -> in .data [0 ];
143
163
144
164
for (i = 0 ; i < linesize ; i ++ ) {
145
- pcm [i ] = Double_field (* in_vector , i );
165
+ pcm [i ] = Double_field (* in_vector , i + offset );
146
166
}
147
167
148
168
return nb_samples ;
149
169
}
150
170
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 ) {
152
173
CAMLparam0 ();
153
174
CAMLlocal1 (fa );
154
175
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!" );
156
180
157
181
if (nb_samples > swr -> in .nb_samples )
158
182
alloc_data (& swr -> in , nb_samples );
@@ -168,21 +192,32 @@ static int get_in_samples_planar_float_array(swr_t *swr, value *in_vector) {
168
192
double * pcm = (double * )swr -> in .data [i ];
169
193
170
194
for (j = 0 ; j < nb_samples ; j ++ ) {
171
- pcm [j ] = Double_field (fa , j );
195
+ pcm [j ] = Double_field (fa , j + offset );
172
196
}
173
197
}
174
198
CAMLreturnT (int , nb_samples );
175
199
}
176
200
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 );
180
212
}
181
213
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 ) {
183
215
CAMLparam0 ();
184
216
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!" );
186
221
187
222
for (int i = 0 ; i < swr -> in .nb_channels ; i ++ ) {
188
223
ba = Field (* in_vector , i );
@@ -192,7 +227,7 @@ static int get_in_samples_planar_ba(swr_t *swr, value *in_vector) {
192
227
"were expected" ,
193
228
i , Caml_ba_array_val (ba )-> dim [0 ], nb_samples );
194
229
195
- swr -> in .data [i ] = Caml_ba_data_val (ba );
230
+ swr -> in .data [i ] = Caml_ba_data_val (ba ) + offset ;
196
231
}
197
232
CAMLreturnT (int , nb_samples );
198
233
}
@@ -415,8 +450,9 @@ static void convert_to_planar_ba(swr_t *swr, int in_nb_samples,
415
450
}
416
451
}
417
452
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 );
420
456
swr_t * swr = Swr_val (_swr );
421
457
422
458
// consistency check between the input channels and the context ones
@@ -434,10 +470,23 @@ CAMLprim value ocaml_swresample_convert(value _swr, value _in_vector) {
434
470
435
471
// acquisition of the input samples and the input number of samples per
436
472
// 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 );
438
479
if (in_nb_samples < 0 )
439
480
ocaml_avutil_raise_error (in_nb_samples );
440
481
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
+
441
490
// Computation of the output number of samples per channel according to the
442
491
// input ones
443
492
int out_nb_samples = swr_get_out_samples (swr -> context , in_nb_samples );
0 commit comments