History

avresample: Introduce AVFrame-based API

Luca Barbato committed 12 years ago

Commit fb1ddcd1 parent 8c6f4306 files · +209 −2Browse files

Unified · Split

6 files
  1. doc/APIchanges +6 −0
  2. libavresample/avresample.h +69 −0
  3. libavresample/utils.c +130 −0
  4. libavresample/version.h +1 −1
  5. libavutil/error.h +2 −0
  6. libavutil/version.h +1 −1
doc/APIchanges+6−0
@@ -13,6 +13,12 @@ libavutil: 2014-08-09 · 12 unmodified lines
1313
1414 API changes, most recent first:
1515
16+2014-04-xx - xxxxxxx - lavr 2.1.0 - avresample.h
17+ Add avresample_convert_frame() and avresample_config().
18+
19+2014-04-xx - xxxxxxx - lavu 54.1.0 - error.h
20+ Add AVERROR_INPUT_CHANGED and AVERROR_OUTPUT_CHANGED.
21+
1622 2014-08-xx - xxxxxxx - lavc 55.57.4 - avcodec.h
1723 Deprecate FF_IDCT_XVIDMMX define and xvidmmx idct option.
1824 Replaced by FF_IDCT_XVID and xvid respectively.
libavresample/avresample.h+69−0
@@ -95,6 +95,7 @@ · 94 unmodified lines
9595 #include "libavutil/avutil.h"
9696 #include "libavutil/channel_layout.h"
9797 #include "libavutil/dict.h"
98+#include "libavutil/frame.h"
9899 #include "libavutil/log.h"
99100 #include "libavutil/mathematics.h"
100101
@@ -165,6 +166,10 @@ AVAudioResampleContext *avresample_alloc_context(void); · 64 unmodified lines
165166
166167 /**
167168 * Initialize AVAudioResampleContext.
169+ * @note The context must be configured using the AVOption API.
170+ *
171+ * @see av_opt_set_int()
172+ * @see av_opt_set_dict()
168173 *
169174 * @param avr audio resample context
170175 * @return 0 on success, negative AVERROR code on failure
@@ -422,6 +427,70 @@ int avresample_available(AVAudioResampleContext *avr); · 251 unmodified lines
422427 */
423428 int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples);
424429
430+/**
431+ * Convert the samples in the input AVFrame and write them to the output AVFrame.
432+ *
433+ * Input and output AVFrames must have channel_layout, sample_rate and format set.
434+ *
435+ * The upper bound on the number of output samples is obtained through
436+ * avresample_get_out_samples().
437+ *
438+ * If the output AVFrame does not have the data pointers allocated the nb_samples
439+ * field will be set using avresample_get_out_samples() and av_frame_get_buffer()
440+ * is called to allocate the frame.
441+ *
442+ * The output AVFrame can be NULL or have fewer allocated samples than required.
443+ * In this case, any remaining samples not written to the output will be added
444+ * to an internal FIFO buffer, to be returned at the next call to this function
445+ * or to avresample_convert() or to avresample_read().
446+ *
447+ * If converting sample rate, there may be data remaining in the internal
448+ * resampling delay buffer. avresample_get_delay() tells the number of
449+ * remaining samples. To get this data as output, call this function or
450+ * avresample_convert() with NULL input.
451+ *
452+ * At the end of the conversion process, there may be data remaining in the
453+ * internal FIFO buffer. avresample_available() tells the number of remaining
454+ * samples. To get this data as output, either call this function or
455+ * avresample_convert() with NULL input or call avresample_read().
456+ *
457+ * If the AVAudioResampleContext configuration does not match the output and
458+ * input AVFrame settings the conversion does not take place and depending on
459+ * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED
460+ * or AVERROR_OUTPUT_CHANGED|AVERROR_INPUT_CHANGED is returned.
461+ *
462+ * @see avresample_get_out_samples()
463+ * @see avresample_available()
464+ * @see avresample_convert()
465+ * @see avresample_read()
466+ * @see avresample_get_delay()
467+ *
468+ * @param avr audio resample context
469+ * @param output output AVFrame
470+ * @param input input AVFrame
471+ * @return 0 on success, AVERROR on failure or nonmatching
472+ * configuration.
473+ */
474+int avresample_convert_frame(AVAudioResampleContext *avr,
475+ AVFrame *output, AVFrame *input);
476+
477+/**
478+ * Configure or reconfigure the AVAudioResampleContext using the information
479+ * provided by the AVFrames.
480+ *
481+ * The original resampling context is reset even on failure.
482+ * The function calls avresample_close() internally if the context is open.
483+ *
484+ * @see avresample_open();
485+ * @see avresample_close();
486+ *
487+ * @param avr audio resample context
488+ * @param output output AVFrame
489+ * @param input input AVFrame
490+ * @return 0 on success, AVERROR on failure.
491+ */
492+int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in);
493+
425494 /**
426495 * @}
427496 */
libavresample/utils.c+130−0
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "libavutil/common.h"
2222 #include "libavutil/dict.h"
2323 #include "libavutil/error.h"
24+#include "libavutil/frame.h"
2425 #include "libavutil/log.h"
2526 #include "libavutil/mem.h"
2627 #include "libavutil/opt.h"
@@ -500,6 +501,135 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, · 473 unmodified lines
500501 current_buffer);
501502 }
502503
504+int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
505+{
506+ if (avresample_is_open(avr)) {
507+ avresample_close(avr);
508+ }
509+
510+ if (in) {
511+ avr->in_channel_layout = in->channel_layout;
512+ avr->in_sample_rate = in->sample_rate;
513+ avr->in_sample_fmt = in->format;
514+ }
515+
516+ if (out) {
517+ avr->out_channel_layout = out->channel_layout;
518+ avr->out_sample_rate = out->sample_rate;
519+ avr->out_sample_fmt = out->format;
520+ }
521+
522+ return 0;
523+}
524+
525+static int config_changed(AVAudioResampleContext *avr,
526+ AVFrame *out, AVFrame *in)
527+{
528+ int ret = 0;
529+
530+ if (in) {
531+ if (avr->in_channel_layout != in->channel_layout ||
532+ avr->in_sample_rate != in->sample_rate ||
533+ avr->in_sample_fmt != in->format) {
534+ ret |= AVERROR_INPUT_CHANGED;
535+ }
536+ }
537+
538+ if (out) {
539+ if (avr->out_channel_layout != out->channel_layout ||
540+ avr->out_sample_rate != out->sample_rate ||
541+ avr->out_sample_fmt != out->format) {
542+ ret |= AVERROR_OUTPUT_CHANGED;
543+ }
544+ }
545+
546+ return ret;
547+}
548+
549+static inline int convert_frame(AVAudioResampleContext *avr,
550+ AVFrame *out, AVFrame *in)
551+{
552+ int ret;
553+ uint8_t **out_data = NULL, **in_data = NULL;
554+ int out_linesize = 0, in_linesize = 0;
555+ int out_nb_samples = 0, in_nb_samples = 0;
556+
557+ if (out) {
558+ out_data = out->extended_data;
559+ out_linesize = out->linesize[0];
560+ out_nb_samples = out->nb_samples;
561+ }
562+
563+ if (in) {
564+ in_data = in->extended_data;
565+ in_linesize = in->linesize[0];
566+ in_nb_samples = in->nb_samples;
567+ }
568+
569+ ret = avresample_convert(avr, out_data, out_linesize,
570+ out_nb_samples,
571+ in_data, in_linesize,
572+ in_nb_samples);
573+
574+ if (ret < 0) {
575+ if (out)
576+ out->nb_samples = 0;
577+ return ret;
578+ }
579+
580+ if (out)
581+ out->nb_samples = ret;
582+
583+ return 0;
584+}
585+
586+static inline int available_samples(AVFrame *out)
587+{
588+ int bytes_per_sample = av_get_bytes_per_sample(out->format);
589+ int samples = out->linesize[0] / bytes_per_sample;
590+
591+ if (av_sample_fmt_is_planar(out->format)) {
592+ return samples;
593+ } else {
594+ int channels = av_get_channel_layout_nb_channels(out->channel_layout);
595+ return samples / channels;
596+ }
597+}
598+
599+int avresample_convert_frame(AVAudioResampleContext *avr,
600+ AVFrame *out, AVFrame *in)
601+{
602+ int ret, setup = 0;
603+
604+ if (!avresample_is_open(avr)) {
605+ if ((ret = avresample_config(avr, out, in)) < 0)
606+ return ret;
607+ if ((ret = avresample_open(avr)) < 0)
608+ return ret;
609+ setup = 1;
610+ } else {
611+ // return as is or reconfigure for input changes?
612+ if ((ret = config_changed(avr, out, in)))
613+ return ret;
614+ }
615+
616+ if (out) {
617+ if (!out->linesize[0]) {
618+ out->nb_samples = avresample_get_out_samples(avr, in->nb_samples);
619+ if ((ret = av_frame_get_buffer(out, 0)) < 0) {
620+ if (setup)
621+ avresample_close(avr);
622+ return ret;
623+ }
624+ } else {
625+ if (!out->nb_samples)
626+ out->nb_samples = available_samples(out);
627+ }
628+ }
629+
630+ return convert_frame(avr, out, in);
631+}
632+
503633 int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
504634 int stride)
505635 {
libavresample/version.h+1−1
@@ -28,7 +28,7 @@ · 27 unmodified lines
2828 #include "libavutil/version.h"
2929
3030 #define LIBAVRESAMPLE_VERSION_MAJOR 2
31−#define LIBAVRESAMPLE_VERSION_MINOR 0
31+#define LIBAVRESAMPLE_VERSION_MINOR 1
3232 #define LIBAVRESAMPLE_VERSION_MICRO 0
3333
3434 #define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
libavutil/error.h+2−0
@@ -60,6 +60,8 @@ · 59 unmodified lines
6060 #define AVERROR_BUG (-0x5fb8aabe) ///< Bug detected, please report the issue
6161 #define AVERROR_UNKNOWN (-0x31b4b1ab) ///< Unknown error, typically from an external library
6262 #define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
63+#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
64+#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
6365
6466 /**
6567 * Put a description of the AVERROR code errnum in errbuf.
libavutil/version.h+1−1
@@ -54,7 +54,7 @@ · 53 unmodified lines
5454 */
5555
5656 #define LIBAVUTIL_VERSION_MAJOR 54
57−#define LIBAVUTIL_VERSION_MINOR 0
57+#define LIBAVUTIL_VERSION_MINOR 1
5858 #define LIBAVUTIL_VERSION_MICRO 0
5959
6060 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t