Beispiel #1
0
int64_t swr_next_pts(struct SwrContext *s, int64_t pts){
    if(pts == INT64_MIN)
        return s->outpts;

    if (s->firstpts == AV_NOPTS_VALUE)
        s->outpts = s->firstpts = pts;

    if(s->min_compensation >= FLT_MAX) {
        return (s->outpts = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate));
    } else {
        int64_t delta = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate) - s->outpts + s->drop_output*(int64_t)s->in_sample_rate;
        double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate);

        if(fabs(fdelta) > s->min_compensation) {
            if(s->outpts == s->firstpts || fabs(fdelta) > s->min_hard_compensation){
                int ret;
                if(delta > 0) ret = swr_inject_silence(s,  delta / s->out_sample_rate);
                else          ret = swr_drop_output   (s, -delta / s-> in_sample_rate);
                if(ret<0){
                    av_log(s, AV_LOG_ERROR, "Failed to compensate for timestamp delta of %f\n", fdelta);
                }
            } else if(s->soft_compensation_duration && s->max_soft_compensation) {
                int duration = s->out_sample_rate * s->soft_compensation_duration;
                double max_soft_compensation = s->max_soft_compensation / (s->max_soft_compensation < 0 ? -s->in_sample_rate : 1);
                int comp = av_clipf(fdelta, -max_soft_compensation, max_soft_compensation) * duration ;
                av_log(s, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", fdelta, comp, duration);
                swr_set_compensation(s, comp, duration);
            }
        }

        return s->outpts;
    }
}
Beispiel #2
0
int AudioController::filter(af_instance *af, mp_audio *data, int /*flags*/) {
	auto ac = priv(af); auto d = ac->d;
	d->af->delay = 0.0;

	Q_ASSERT(d->mixer != nullptr);
	if (d->dirty) {
		if (d->dirty & Amp)
			d->mixer->setAmp(d->amp);
		if (d->dirty & Normalizer)
			d->mixer->setNormalizer(d->normalizerActivated, d->normalizerOption);
		if (d->dirty & ChMap)
			d->mixer->setChannelLayoutMap(d->map);
		if (d->dirty & Scale)
			d->mixer->setScaler(d->tempoScalerActivated, d->scale);
		d->dirty = 0;
	}

	const mp_audio *in = data;
	if (d->resample) {
		const int frames_delay = swr_get_delay(d->swr, data->rate);
		const int frames = av_rescale_rnd(frames_delay + data->samples, d->resampled->rate, data->rate, AV_ROUND_UP);
		mp_audio_realloc_min(d->resampled, frames);
		d->af->delay = (double)frames/data->rate;
		if ((d->resampled->samples = frames))
			d->resampled->samples = swr_convert(d->swr, (uchar**)d->resampled->planes, d->resampled->samples, (const uchar**)data->planes, data->samples);
		in = d->resampled;
	}
	d->mixer->apply(in);
	*data = *d->af->data;
	af->delay += d->mixer->delay();

	return 0;
}
Beispiel #3
0
/*
 * encode one audio frame and send it to the muxer
 * return 1 when encoding is finished, 0 otherwise
 */
static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
{
    AVCodecContext *c;
    AVPacket pkt = { 0 }; // data and size must be 0;
    AVFrame *frame;
    int ret;
    int got_packet;
    int dst_nb_samples;
    
    av_init_packet(&pkt);
    c = ost->st->codec;
    
    frame = get_audio_frame(ost);
    
    if (frame) {
        /* convert samples from native format to destination codec format, using the resampler */
        /* compute destination number of samples */
        dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
                                        c->sample_rate, c->sample_rate, AV_ROUND_UP);
        av_assert0(dst_nb_samples == frame->nb_samples);
        
        /* when we pass a frame to the encoder, it may keep a reference to it
         * internally;
         * make sure we do not overwrite it here
         */
        ret = av_frame_make_writable(ost->frame);
        if (ret < 0)
            exit(1);
        
        /* convert to destination format */
        ret = swr_convert(ost->swr_ctx,
                          ost->frame->data, dst_nb_samples,
                          (const uint8_t **)frame->data, frame->nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error while converting\n");
            exit(1);
        }
        frame = ost->frame;
        
        frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base);
        ost->samples_count += dst_nb_samples;
    }
    
    ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
    if (ret < 0) {
        fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
        exit(1);
    }
    
    if (got_packet) {
        ret = write_frame(oc, &c->time_base, ost->st, &pkt);
        if (ret < 0) {
            fprintf(stderr, "Error while writing audio frame: %s\n",
                    av_err2str(ret));
            exit(1);
        }
    }
    
    return (frame || got_packet) ? 0 : 1;
}
AudioPlayerLoader::ReadResult ChildFFMpegLoader::readFromReadyFrame(QByteArray &result, int64 &samplesAdded) {
	int res = 0;

	if (_dstSamplesData) { // convert needed
		int64_t dstSamples = av_rescale_rnd(swr_get_delay(_swrContext, _srcRate) + _frame->nb_samples, _dstRate, _srcRate, AV_ROUND_UP);
		if (dstSamples > _maxResampleSamples) {
			_maxResampleSamples = dstSamples;
			av_free(_dstSamplesData[0]);

			if ((res = av_samples_alloc(_dstSamplesData, 0, AudioToChannels, _maxResampleSamples, AudioToFormat, 1)) < 0) {
				_dstSamplesData[0] = 0;
				char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
				LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
				return ReadResult::Error;
			}
		}
		if ((res = swr_convert(_swrContext, _dstSamplesData, dstSamples, (const uint8_t**)_frame->extended_data, _frame->nb_samples)) < 0) {
			char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
			LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
			return ReadResult::Error;
		}
		int32 resultLen = av_samples_get_buffer_size(0, AudioToChannels, res, AudioToFormat, 1);
		result.append((const char*)_dstSamplesData[0], resultLen);
		samplesAdded += resultLen / _sampleSize;
	} else {
		result.append((const char*)_frame->extended_data[0], _frame->nb_samples * _sampleSize);
		samplesAdded += _frame->nb_samples;
	}
	return ReadResult::Ok;
}
Beispiel #5
0
static int get_out_samples(struct af_resample *s, int in_samples)
{
#if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2
    return swr_get_out_samples(s->avrctx, in_samples);
#else
    return av_rescale_rnd(in_samples, s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP)
           + swr_get_delay(s->avrctx, s->ctx.out_rate);
#endif
}
Beispiel #6
0
boost::int64_t AudioResampleImpl::resultSamples(boost::int64_t sourceSamples) const
{
	if (!m_resampler)
		return 0;

    return av_rescale_rnd(
                swr_get_delay(m_resampler.get(), m_from.sampleRate()) + sourceSamples,
                m_to.sampleRate(), m_from.sampleRate(), AV_ROUND_UP);
}
Beispiel #7
0
static int WriteAudioFrame(AVFormatContext *oc, OutputStream *ost, AVI6 *avi)
{
	AVCodecContext *c = NULL;
	AVPacket pkt = { 0 };
	AVFrame *frame = NULL;
	int ret = 0;
	int got_packet = 0;
	int dst_nb_samples = 0;

	av_init_packet(&pkt);
	c = ost->st->codec;

	frame = GetAudioFrame(ost, avi);

	if (frame) {
		// フォーマット変換後のサンプル数を決定
		dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, frame->sample_rate) + frame->nb_samples,
										c->sample_rate, c->sample_rate, AV_ROUND_UP);
		//av_assert0(dst_nb_samples == frame->nb_samples);

		// フレームを書き込み可能にする
		ret = av_frame_make_writable(ost->frame);
		if (ret < 0)
			exit(1);

		// 音声フォーマットを変換
		ret = swr_convert(ost->swr_ctx,
						  ost->frame->data, dst_nb_samples,
						  (const uint8_t **)frame->data, frame->nb_samples);
		if (ret < 0) {
			fprintf(stderr, "Error while converting\n");
			return 0;
		}
		frame = ost->frame;

		frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base);
		ost->samples_count += dst_nb_samples;

		ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
		if (ret < 0) {
			fprintf(stderr, "Error encoding audio frame: %s\n", MakeErrorString(ret));
			return 0;
		}

		if (got_packet) {
			ret = WriteFrame(oc, &c->time_base, ost->st, &pkt);
			if (ret < 0) {
				fprintf(stderr, "Error while writing audio frame: %s\n",
						MakeErrorString(ret));
				return 0;
			}
		}
	}

	return (frame || got_packet) ? 0 : 1;
}
Beispiel #8
0
    int MpegLoader::readMore(QByteArray &result, qint64 &samplesAdded) 
    {
        int res;
        if ((res = av_read_frame(FmtContext_, &Avpkt_)) < 0)
            return -1;

        if (Avpkt_.stream_index == StreamId_) 
        {
            av_frame_unref(Frame_);
            int got_frame = 0;
            if ((res = avcodec_decode_audio4(CodecContext_, Frame_, &got_frame, &Avpkt_)) < 0) 
            {
                av_packet_unref(&Avpkt_);
                if (res == AVERROR_INVALIDDATA) 
                    return 0;
                return -1;
            }

            if (got_frame) 
            {
                if (OutSamplesData_) 
                {
                    int64_t dstSamples = av_rescale_rnd(swr_get_delay(SwrContext_, SrcRate_) + Frame_->nb_samples, DstRate_, SrcRate_, AV_ROUND_UP);
                    if (dstSamples > MaxResampleSamples_) 
                    {
                        MaxResampleSamples_ = dstSamples;
                        av_free(OutSamplesData_[0]);

                        if ((res = av_samples_alloc(OutSamplesData_, 0, OutChannels, MaxResampleSamples_, OutFormat, 1)) < 0) 
                        {
                            OutSamplesData_[0] = 0;
                            av_packet_unref(&Avpkt_);
                            return -1;
                        }
                    }

                    if ((res = swr_convert(SwrContext_, OutSamplesData_, dstSamples, (const uint8_t**)Frame_->extended_data, Frame_->nb_samples)) < 0) 
                    {
                        av_packet_unref(&Avpkt_);
                        return -1;
                    }

                    qint32 resultLen = av_samples_get_buffer_size(0, OutChannels, res, OutFormat, 1);
                    result.append((const char*)OutSamplesData_[0], resultLen);
                    samplesAdded += resultLen / SampleSize_;
                } 
                else 
                {
                    result.append((const char*)Frame_->extended_data[0], Frame_->nb_samples * SampleSize_);
                    samplesAdded += Frame_->nb_samples;
                }
            }
        }
        av_packet_unref(&Avpkt_);
        return 1;
    }
Beispiel #9
0
static int ffmpeg_decode(struct ffmpeg_file *file)
{
    if (file->pkt_decoded >= file->pkt->size) {
        int e = av_read_frame(file->format, file->pkt);
        if (e < 0) {
            return e;
        }
        file->pkt_decoded = 0;
    }

    int got_frame = 0;
    int e = avcodec_decode_audio4(file->codec, file->frame, &got_frame,
            file->pkt);
    if (e < 0) {
        return e;
    }
    if (!got_frame) {
        return 0;
    }
    file->pkt_decoded += e;

    AVFrame *frame = file->frame;
    int delay_nsamples = swr_get_delay(file->swr, file->codec->sample_rate);
    int dst_nsamples = av_rescale_rnd(delay_nsamples + frame->nb_samples,
            file->sample_rate, file->codec->sample_rate, AV_ROUND_UP);
    if (file->buf_nsamples < dst_nsamples) {
        if (file->buf) {
            av_freep(&file->buf[0]);
        }
        av_freep(&file->buf);
        int e = av_samples_alloc_array_and_samples(&file->buf, NULL,
                file->channels, file->sample_rate, file->sample_fmt, 0);
        if (e < 0) {
            return e;
        }
        file->buf_nsamples = dst_nsamples;
    }

    int ns = swr_convert(file->swr, file->buf, dst_nsamples,
            (const uint8_t**) frame->data, frame->nb_samples);
    int nb = av_samples_get_buffer_size(NULL, file->channels,
            ns, file->sample_fmt, 1);
    if (nb < 0) {
        return nb;
    }
    file->buf_len = nb;
    file->buf_offset = 0;
    if (file->frame->pts > 0) {
        file->time = file->frame->pts;
    }

    return nb;
}
Beispiel #10
0
BOOL CVideoLivRecord::write_audio_frame(AVStream *st, void* pBuffer, LONG len)
{
	AVCodecContext* avcc = st->codec;
	AVPacket pkt = {0};
	av_init_packet(&pkt);
	AVFrame* frame = get_audio_frame(st, pBuffer, len);
	int ret = 0;
	int dst_nb_samples = 0;
	if (frame){
		dst_nb_samples = (int)av_rescale_rnd(swr_get_delay(m_pAudioSwrctx, avcc->sample_rate) + frame->nb_samples,
			avcc->sample_rate, avcc->sample_rate, AV_ROUND_UP);
		av_assert0(dst_nb_samples == frame->nb_samples);
		ret = av_frame_make_writable(m_pAudioFrame);
		if (ret < 0){
			log("[CVideoLivRecord::write_audio_frame] -- av_frame_make_writable() error");
			return FALSE;
		}
		ret = swr_convert(m_pAudioSwrctx, m_pAudioFrame->data, dst_nb_samples, 
			             (const uint8_t**)frame->data, frame->nb_samples);
		if (ret < 0){
			log("[CVideoLivRecord::write_audio_frame] -- av_frame_make_writable() error");
			return FALSE;
		}
		frame = m_pAudioFrame;
		AVRational tmp = {1, avcc->sample_rate};

		frame->pts = av_rescale_q(m_AudioSamplesCount, tmp, avcc->time_base);
		m_AudioSamplesCount += dst_nb_samples;
	}
	int got_packet = 0;
	ret = avcodec_encode_audio2(avcc, &pkt, frame, &got_packet);
	if (ret < 0){
		log("[CVideoLivRecord::write_audio_frame] -- avcodec_encode_audio2() error");
		return FALSE;
	}
	if(got_packet){
		av_packet_rescale_ts(&pkt, avcc->time_base, st->time_base);
		pkt.stream_index = st->index;
		ret = av_interleaved_write_frame(m_pAVFormatContext, &pkt);
		//ret = write_audio_frame(m_pAudioStream, pBuffer, len);
		if (ret < 0){
			log("[CVideoLivRecord::write_audio_frame] -- write_audio_frame() error");
			return FALSE;
		}
	}
	return (frame || got_packet)? FALSE : TRUE;
}
Beispiel #11
0
int create_channel_data( AVFrame *pFrame )
{
        //printf( "In Create Channel data : Thread 1\n" );
        int dst_nb_channels = av_get_channel_layout_nb_channels
                              ( AV_CH_LAYOUT_STEREO );
        int dst_linesize;
        int delay = swr_get_delay( gMedia->pSwrContext,
                                   pFrame->sample_rate );
        int dst_nb_samples = av_rescale_rnd( pFrame->nb_samples + delay,
                                             pFrame->sample_rate,
                                             pFrame->sample_rate,
                                             AV_ROUND_UP );
        //printf("Destination channels = %d\n",dst_nb_channels);
        //printf("Destination samples = %d\n",dst_nb_samples);
        int error_check = av_samples_alloc_array_and_samples
                          ( &gMedia->audio_buf,
                            &dst_linesize,
                            dst_nb_channels,
                            dst_nb_samples,
                            AV_SAMPLE_FMT_FLT,
                            1 );

        if ( error_check < 0 ) {
                fprintf( stderr, "Could not allocate destination samples\n" );
        }

        int data_size = av_samples_get_buffer_size
                        ( NULL,
                          pFrame->channels,
                          pFrame->nb_samples,
                          pFrame->format,
                          0 );
        /*      printf("Number of samples = %d\n",pFrame->nb_samples);
                printf("Number of bytes = %d\n",pFrame->nb_samples*2*4);
                printf("Linesize per channel is %d\n",pFrame->linesize[0]);
                printf("Calculated datasize is %d\n",data_size);
        */
        swr_convert( gMedia->pSwrContext,
                     ( uint8_t ** )( gMedia->audio_buf ) ,
                     pFrame->nb_samples,
                     ( const uint8_t ** )pFrame->data,
                     pFrame->nb_samples );
        return data_size;
}
Beispiel #12
0
int submitAudioFrame(char *data, int length, long frameTimestamp) {
    AVPacket pkt;
    int ret;
    AVFrame *frame;
    int got_packet;
    int sampleCount;

    // If no stream header has been written yet, don't do anything
    if (hasWrittenStreamHeader == 0) {
        return 0;
    }

    frame = avcodec_alloc_frame();
    if (frame == NULL) {
        fprintf(stderr, "Failed to allocate frame\n");
        return -1;
    }

    av_init_packet(&pkt);

    // Copy our data in
    memcpy(srcSamplesData[0], data, length);
    srcSamplesCount = length / 4;

    // Resample to floating point
    sampleCount = av_rescale_rnd(swr_get_delay(swrContext, audioCodecCtx->sample_rate) + srcSamplesCount,
        audioCodecCtx->sample_rate, audioCodecCtx->sample_rate, AV_ROUND_UP);
    if (sampleCount > maxDstSamplesCount) {
        // Need to resize the buffer
        av_free(dstSamplesData[0]);

        ret = av_samples_alloc(dstSamplesData, &dstSamplesLinesize, audioCodecCtx->channels,
            sampleCount, audioCodecCtx->sample_fmt, 0);
        if (ret < 0) {
            fprintf(stderr, "av_samples_alloc() failed: %d\n", ret);
            return ret;
        }

        maxDstSamplesCount = sampleCount;
        dstSamplesSize = av_samples_get_buffer_size(NULL, audioCodecCtx->channels, sampleCount,
            audioCodecCtx->sample_fmt, 0);
    }

    ret = swr_convert(swrContext, dstSamplesData, sampleCount,
        (const unsigned char **)srcSamplesData, srcSamplesCount);
    if (ret < 0) {
        fprintf(stderr, "swr_convert() failed: %d\n", ret);
        return ret;
    }

    frame->nb_samples = sampleCount;
    ret = avcodec_fill_audio_frame(frame, audioCodecCtx->channels,
        audioCodecCtx->sample_fmt, dstSamplesData[0], dstSamplesSize, 0);
    if (ret < 0) {
        fprintf(stderr, "avcodec_fill_audio_frame() failed: %d\n", ret);
        avcodec_free_frame(&frame);
                    return ret;
    }

    // pkt is freed on failure or !got_packet
    pkt.data = NULL;
    pkt.size = 0;
    ret = avcodec_encode_audio2(audioCodecCtx, &pkt, frame, &got_packet);
    if (ret < 0) {
        fprintf(stderr, "avcodec_encode_audio2() failed: %d\n", ret);
        avcodec_free_frame(&frame);
                    return ret;

    }

    if (!got_packet) {
        // Nothing to do here
        return 0;
    }

    pkt.stream_index = audioStream->index;

    pkt.pts = frameTimestamp;

    pthread_mutex_lock(&streamLock);
    ret = av_interleaved_write_frame(formatContext, &pkt);
    pthread_mutex_unlock(&streamLock);

    avcodec_free_frame(&frame);
    av_free_packet(&pkt);

    if (ret != 0) {
        fprintf(stderr, "av_interleaved_write_frame() failed: %d\n", ret);
                    return ret;

    }

    return 0;
}
Beispiel #13
0
	status_t FFMPEGer::encodeAudio(MediaBuffer* src, MediaBuffer* dst){
		AVCodecContext *c;
		
		AVFrame *frame = NULL;
		int ret;
		int got_packet;
		int dst_nb_samples;
		OutputStream* ost = &audio_st;
		
		unsigned char* srcData = (unsigned char*)src->data() + src->range_offset();
		int copySize = getAudioEncodeBufferSize();

		while(srcData < ((unsigned char*)src->data() + src->range_offset() + src->range_length())){
			AVPacket pkt = { 0 }; // data and size must be 0;
			av_init_packet(&pkt);
			c = ost->st->codec;
		
			frame = audio_st.tmp_frame;
			memcpy(frame->data[0], srcData, copySize);
			srcData += copySize;
			frame->pts = audio_st.next_pts;
			
			audio_st.next_pts += frame->nb_samples;

			if (frame) {
				/* convert samples from native format to destination codec format, using the resampler */
				/* compute destination number of samples */
				dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
												c->sample_rate, c->sample_rate, AV_ROUND_UP);
				av_assert0(dst_nb_samples == frame->nb_samples);

				/* when we pass a frame to the encoder, it may keep a reference to it
				 * internally;
				 * make sure we do not overwrite it here
				 */
				ret = av_frame_make_writable(ost->frame);
				if (ret < 0)
					return UNKNOWN_ERROR;

				/* convert to destination format */
				ret = swr_convert(ost->swr_ctx,
								  ost->frame->data, dst_nb_samples,
								  (const uint8_t **)frame->data, frame->nb_samples);
				if (ret < 0) {
					ALOGE("Error while converting");
					return UNKNOWN_ERROR;
				}
				
				frame = ost->frame;
				frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base);
				ost->samples_count += dst_nb_samples;
			}

			ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
			if (ret < 0) {
				ALOGE("Error encoding audio frame: %s", av_err2str(ret));
				return UNKNOWN_ERROR;
			}

			pkt.pts = frame->pts;//
			
#if 0
			static int count = 0;
			char a[50] = {0};
			sprintf(a, "/sdcard/pcm%d", count++);
			FILE* f1 = fopen(a, "ab");
			if(f1 != NULL){
				size_t res = fwrite(pkt.data, 1, pkt.size, f1);
				fclose(f1);
				ALOGV("fwrite %d of %d to /sdcard/pcm!", res, pkt.size);
			}else
				ALOGE("can not fopen /sdcard/pcm!!");
#endif
			
			
			if (got_packet) {
				ret = write_frame(fmt_ctx, &c->time_base, ost->st, &pkt);
				if (ret < 0) {
					ALOGE("Error while writing audio frame: %s", av_err2str(ret));
					return UNKNOWN_ERROR;
				}
			}
		}
	}
Beispiel #14
0
int main(int argc, char **argv)
{
    int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND;
    int src_rate = 48000, dst_rate = 44100;
    uint8_t **src_data = NULL, **dst_data = NULL;
    int src_nb_channels = 0, dst_nb_channels = 0;
    int src_linesize, dst_linesize;
    int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples;
    enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16;
    const char *dst_filename = NULL;
    FILE *dst_file;
    int dst_bufsize;
    const char *fmt;
    struct SwrContext *swr_ctx;
    double t;
    int ret;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s output_file\n"
                "API example program to show how to resample an audio stream with libswresample.\n"
                "This program generates a series of audio frames, resamples them to a specified "
                "output format and rate and saves them to an output file named output_file.\n",
            argv[0]);
        exit(1);
    }
    dst_filename = argv[1];

    dst_file = fopen(dst_filename, "wb");
    if (!dst_file) {
        fprintf(stderr, "Could not open destination file %s\n", dst_filename);
        exit(1);
    }

    /* create resampler context */
    swr_ctx = swr_alloc();
    if (!swr_ctx) {
        fprintf(stderr, "Could not allocate resampler context\n");
        ret = AVERROR(ENOMEM);
        goto end;
    }

    /* set options */
    av_opt_set_int(swr_ctx, "in_channel_layout",    src_ch_layout, 0);
    av_opt_set_int(swr_ctx, "in_sample_rate",       src_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);

    av_opt_set_int(swr_ctx, "out_channel_layout",    dst_ch_layout, 0);
    av_opt_set_int(swr_ctx, "out_sample_rate",       dst_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);

    /* initialize the resampling context */
    if ((ret = swr_init(swr_ctx)) < 0) {
        fprintf(stderr, "Failed to initialize the resampling context\n");
        goto end;
    }

    /* allocate source and destination samples buffers */

    src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
    ret = alloc_samples_array_and_data(&src_data, &src_linesize, src_nb_channels,
                                       src_nb_samples, src_sample_fmt, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate source samples\n");
        goto end;
    }

    /* compute the number of converted samples: buffering is avoided
     * ensuring that the output buffer will contain at least all the
     * converted input samples */
    max_dst_nb_samples = dst_nb_samples =
        av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

    /* buffer is going to be directly written to a rawaudio file, no alignment */
    dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
    ret = alloc_samples_array_and_data(&dst_data, &dst_linesize, dst_nb_channels,
                                       dst_nb_samples, dst_sample_fmt, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate destination samples\n");
        goto end;
    }

    t = 0;
    do {
        /* generate synthetic audio */
        fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t);

        /* compute destination number of samples */
        dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) +
                                        src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
        if (dst_nb_samples > max_dst_nb_samples) {
            av_free(dst_data[0]);
            ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
                                   dst_nb_samples, dst_sample_fmt, 1);
            if (ret < 0)
                break;
            max_dst_nb_samples = dst_nb_samples;
        }

        /* convert to destination format */
        ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error while converting\n");
            goto end;
        }
        dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                 ret, dst_sample_fmt, 1);
        printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
        fwrite(dst_data[0], 1, dst_bufsize, dst_file);
    } while (t < 10);

    if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt) < 0))
        goto end;
    fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n"
            "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n",
            fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename);

end:
    if (dst_file)
        fclose(dst_file);

    if (src_data)
        av_freep(&src_data[0]);
    av_freep(&src_data);

    if (dst_data)
        av_freep(&dst_data[0]);
    av_freep(&dst_data);

    swr_free(&swr_ctx);
    return ret < 0;
}
Beispiel #15
0
AkPacket ConvertAudioFFmpeg::convert(const AkAudioPacket &packet,
                                     const AkCaps &oCaps)
{
    AkAudioCaps oAudioCaps(oCaps);

    int64_t iSampleLayout = channelLayouts->value(packet.caps().layout(), 0);

    AVSampleFormat iSampleFormat =
            av_get_sample_fmt(AkAudioCaps::sampleFormatToString(packet.caps().format())
                              .toStdString().c_str());

    int iSampleRate = packet.caps().rate();
    int iNChannels = packet.caps().channels();
    int iNSamples = packet.caps().samples();

    int64_t oSampleLayout = channelLayouts->value(oAudioCaps.layout(),
                                                  AV_CH_LAYOUT_STEREO);

    AVSampleFormat oSampleFormat =
            av_get_sample_fmt(AkAudioCaps::sampleFormatToString(oAudioCaps.format())
                              .toStdString().c_str());

    int oSampleRate = oAudioCaps.rate();
    int oNChannels = oAudioCaps.channels();

    this->m_resampleContext =
            swr_alloc_set_opts(this->m_resampleContext,
                               oSampleLayout,
                               oSampleFormat,
                               oSampleRate,
                               iSampleLayout,
                               iSampleFormat,
                               iSampleRate,
                               0,
                               NULL);

    if (!this->m_resampleContext)
        return AkPacket();

    // Create input audio frame.
    static AVFrame iFrame;
    memset(&iFrame, 0, sizeof(AVFrame));
    iFrame.format = iSampleFormat;
    iFrame.channels = iNChannels;
    iFrame.channel_layout = uint64_t(iSampleLayout);
    iFrame.sample_rate = iSampleRate;
    iFrame.nb_samples = iNSamples;
    iFrame.pts = iFrame.pkt_pts = packet.pts();

    if (avcodec_fill_audio_frame(&iFrame,
                                 iFrame.channels,
                                 iSampleFormat,
                                 reinterpret_cast<const uint8_t *>(packet.buffer().constData()),
                                 packet.buffer().size(),
                                 1) < 0) {
        return AkPacket();
    }

    // Fill output audio frame.
    AVFrame oFrame;
    memset(&oFrame, 0, sizeof(AVFrame));
    oFrame.format = oSampleFormat;
    oFrame.channels = oNChannels;
    oFrame.channel_layout = uint64_t(oSampleLayout);
    oFrame.sample_rate = oSampleRate;
    oFrame.nb_samples = int(swr_get_delay(this->m_resampleContext, oSampleRate))
                        + iFrame.nb_samples
                        * oSampleRate
                        / iSampleRate
                        + 3;
    oFrame.pts = oFrame.pkt_pts = iFrame.pts * oSampleRate / iSampleRate;

    // Calculate the size of the audio buffer.
    int frameSize = av_samples_get_buffer_size(oFrame.linesize,
                                               oFrame.channels,
                                               oFrame.nb_samples,
                                               oSampleFormat,
                                               1);

    QByteArray oBuffer(frameSize, Qt::Uninitialized);

    if (avcodec_fill_audio_frame(&oFrame,
                                 oFrame.channels,
                                 oSampleFormat,
                                 reinterpret_cast<const uint8_t *>(oBuffer.constData()),
                                 oBuffer.size(),
                                 1) < 0) {
        return AkPacket();
    }

    // convert to destination format
    if (swr_convert_frame(this->m_resampleContext,
                          &oFrame,
                          &iFrame) < 0)
        return AkPacket();

    frameSize = av_samples_get_buffer_size(oFrame.linesize,
                                           oFrame.channels,
                                           oFrame.nb_samples,
                                           oSampleFormat,
                                           1);

    oBuffer.resize(frameSize);

    AkAudioPacket oAudioPacket;
    oAudioPacket.caps() = oAudioCaps;
    oAudioPacket.caps().samples() = oFrame.nb_samples;
    oAudioPacket.buffer() = oBuffer;
    oAudioPacket.pts() = oFrame.pts;
    oAudioPacket.timeBase() = AkFrac(1, oAudioCaps.rate());
    oAudioPacket.index() = packet.index();
    oAudioPacket.id() = packet.id();

    return oAudioPacket.toPacket();
}
Beispiel #16
0
CBaseDec::RetCode CFfmpegDec::Decoder(FILE *_in, int /*OutputFd*/, State* state, CAudioMetaData* _meta_data, time_t* time_played, unsigned int* secondsToSkip)
{
	in = _in;
	RetCode Status=OK;
	is_stream = fseek((FILE *)in, 0, SEEK_SET);

	if (!SetMetaData((FILE *)in, _meta_data, true)) {
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	AVCodecContext *c = avc->streams[best_stream]->codec;

	mutex.lock();
	int r = avcodec_open2(c, codec, NULL);
	mutex.unlock();
	if (r)
	{
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	SwrContext *swr = swr_alloc();
	if (!swr) {
		mutex.lock();
		avcodec_close(c);
		mutex.unlock();
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	mSampleRate = samplerate;
	mChannels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
#if __BYTE_ORDER == __LITTLE_ENDIAN
	audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 1);
#else
	audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 0);
#endif

	AVFrame *frame = NULL;
	AVPacket rpacket;
	av_init_packet(&rpacket);

	av_opt_set_int(swr, "in_channel_layout",	c->channel_layout,	0);
	//av_opt_set_int(swr, "out_channel_layout",	c->channel_layout,	0);
	av_opt_set_int(swr, "out_channel_layout",	AV_CH_LAYOUT_STEREO,	0);
	av_opt_set_int(swr, "in_sample_rate",		c->sample_rate,		0);
	av_opt_set_int(swr, "out_sample_rate",		c->sample_rate,		0);
	av_opt_set_int(swr, "in_sample_fmt",		c->sample_fmt,		0);
	av_opt_set_int(swr, "out_sample_fmt",		AV_SAMPLE_FMT_S16,	0);

	swr_init(swr);

	uint8_t *outbuf = NULL;
	int outsamples = 0;
	int outsamples_max = 0;

	int64_t pts = 0, start_pts = 0, next_skip_pts = 0;
	uint64_t skip = 0;
	int seek_flags = 0;

	do
	{
		int actSecsToSkip = *secondsToSkip;
		if (!is_stream && (actSecsToSkip || *state==FF || *state==REV) && avc->streams[best_stream]->time_base.num) {
			if (!next_skip_pts || pts >= next_skip_pts) {
				skip = avc->streams[best_stream]->time_base.den / avc->streams[best_stream]->time_base.num;
				if (actSecsToSkip)
					skip *= actSecsToSkip;
				if (*state == REV) {
					next_skip_pts = pts - skip;
					pts = next_skip_pts - skip/4;
					seek_flags = AVSEEK_FLAG_BACKWARD;
					if (pts < start_pts) {
						pts = start_pts;
						*state = PAUSE; 
					}
				} else {
					pts += skip;
					next_skip_pts = pts + skip/4;
					seek_flags = 0;
				}
				av_seek_frame(avc, best_stream, pts, seek_flags);
				skip = 0;
				// if a custom value was set we only jump once
				if (actSecsToSkip != 0) {
					*state=PLAY;
					*secondsToSkip = 0;
				}
			}
		}

		while(*state==PAUSE && !is_stream)
			usleep(10000);

		if (av_read_frame(avc, &rpacket)) {
			Status=DATA_ERR;
			break;
		}

		if (rpacket.stream_index != best_stream) {
			av_free_packet(&rpacket);
			continue;
		}

		AVPacket packet = rpacket;
		while (packet.size > 0) {
			int got_frame = 0;
			if (!frame) {
				if (!(frame = avcodec_alloc_frame())) {
					Status=DATA_ERR;
					break;
				}
			} else
				avcodec_get_frame_defaults(frame);

			int len = avcodec_decode_audio4(c, frame, &got_frame, &packet);
			if (len < 0) {
				// skip frame
				packet.size = 0;
				avcodec_flush_buffers(c);
				mutex.lock();
				avcodec_close(c);
				avcodec_open2(c, codec, NULL);
				mutex.unlock();
				continue;
			}
			if (got_frame && *state!=PAUSE) {
				int out_samples;
				outsamples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + frame->nb_samples,
					c->sample_rate, c->sample_rate, AV_ROUND_UP);
				if (outsamples > outsamples_max) {
					av_free(outbuf);
					if (av_samples_alloc(&outbuf, &out_samples, mChannels, //c->channels,
								frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) {
						Status=WRITE_ERR;
						packet.size = 0;
						break;
					}
					outsamples_max = outsamples;
				}
				outsamples = swr_convert(swr, &outbuf, outsamples,
							(const uint8_t **) &frame->data[0], frame->nb_samples);
				int outbuf_size = av_samples_get_buffer_size(&out_samples, mChannels, //c->channels,
									  outsamples, AV_SAMPLE_FMT_S16, 1);

				if(audioDecoder->WriteClip((unsigned char*) outbuf, outbuf_size) != outbuf_size)
				{
					fprintf(stderr,"%s: PCM write error (%s).\n", ProgName, strerror(errno));
					Status=WRITE_ERR;
				}
				pts = av_frame_get_best_effort_timestamp(frame);
				if (!start_pts)
					start_pts = pts;
			}
			packet.size -= len;
			packet.data += len;
		}
		if (time_played && avc->streams[best_stream]->time_base.den)
			*time_played = (pts - start_pts) * avc->streams[best_stream]->time_base.num / avc->streams[best_stream]->time_base.den;
		av_free_packet(&rpacket);
	} while (*state!=STOP_REQ && Status==OK);

	audioDecoder->StopClip();
	meta_data_valid = false;

	swr_free(&swr);
	av_free(outbuf);
	av_free_packet(&rpacket);
	avcodec_free_frame(&frame);
	avcodec_close(c);
	//av_free(avcc);

	DeInit();
	if (_meta_data->cover_temporary && !_meta_data->cover.empty()) {
		_meta_data->cover_temporary = false;
		unlink(_meta_data->cover.c_str());
	}
	return Status;
}
Beispiel #17
0
static void write_audio_frame(AVFormatContext *oc, AVStream *st)
{
    AVCodecContext *c;
    AVPacket pkt = { 0 }; // data and size must be 0;
    int got_packet, ret, dst_nb_samples;

    av_init_packet(&pkt);
    c = st->codec;

    get_audio_frame((int16_t *)src_samples_data[0], src_nb_samples, c->channels);

    /* convert samples from native format to destination codec format, using the resampler */
    if (swr_ctx) {
        /* compute destination number of samples */
        dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + src_nb_samples,
                                        c->sample_rate, c->sample_rate, AV_ROUND_UP);
        if (dst_nb_samples > max_dst_nb_samples) {
            av_free(dst_samples_data[0]);
            ret = av_samples_alloc(dst_samples_data, &dst_samples_linesize, c->channels,
                                   dst_nb_samples, c->sample_fmt, 0);
            if (ret < 0)
                exit(1);
            max_dst_nb_samples = dst_nb_samples;
            dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples,
                                                          c->sample_fmt, 0);
        }

        /* convert to destination format */
        ret = swr_convert(swr_ctx,
                          dst_samples_data, dst_nb_samples,
                          (const uint8_t **)src_samples_data, src_nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error while converting\n");
            exit(1);
        }
    } else {
        dst_nb_samples = src_nb_samples;
    }

    audio_frame->nb_samples = dst_nb_samples;
    audio_frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base);
    avcodec_fill_audio_frame(audio_frame, c->channels, c->sample_fmt,
                             dst_samples_data[0], dst_samples_size, 0);
    samples_count += dst_nb_samples;

    ret = avcodec_encode_audio2(c, &pkt, audio_frame, &got_packet);
    if (ret < 0) {
        fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
        exit(1);
    }

    if (!got_packet)
        return;

    /* rescale output packet timestamp values from codec to stream timebase */
    pkt.pts = av_rescale_q_rnd(pkt.pts, c->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
    pkt.dts = av_rescale_q_rnd(pkt.dts, c->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
    pkt.duration = av_rescale_q(pkt.duration, c->time_base, st->time_base);
    pkt.stream_index = st->index;

    /* Write the compressed frame to the media file. */
    ret = av_interleaved_write_frame(oc, &pkt);
    if (ret != 0) {
        fprintf(stderr, "Error while writing audio frame: %s\n",
                av_err2str(ret));
        exit(1);
    }
}
void ACapsConvertElement::iStream(const QbPacket &packet)
{
    if (!packet.caps().isValid() ||
        packet.caps().mimeType() != "audio/x-raw" ||
        this->state() != ElementStatePlaying)
        return;

    // Input Format
    AVSampleFormat iSampleFormat = av_get_sample_fmt(packet.caps().property("format").toString().toStdString().c_str());
    int iNChannels = packet.caps().property("channels").toInt();
    int64_t iChannelLayout = av_get_channel_layout(packet.caps().property("layout").toString().toStdString().c_str());
    int iNPlanes = av_sample_fmt_is_planar(iSampleFormat)? iNChannels: 1;
    int iSampleRate = packet.caps().property("rate").toInt();
    int iNSamples = packet.caps().property("samples").toInt();

    if (iNSamples < 1)
        iNSamples = 1024;

    bool sameMimeType = packet.caps().mimeType() == this->m_caps.mimeType();

    // Output Format
    AVSampleFormat oSampleFormat = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("format"))?
                                        av_get_sample_fmt(this->m_caps.property("format").toString().toStdString().c_str()):
                                        iSampleFormat;

    int oNChannels = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("channels"))?
                         this->m_caps.property("channels").toInt():
                         iNChannels;

    int64_t oChannelLayout = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("layout"))?
                                 av_get_channel_layout(this->m_caps.property("layout").toString().toStdString().c_str()):
                                 iChannelLayout;

    int oSampleRate = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("rate"))?
                          this->m_caps.property("rate").toInt():
                          iSampleRate;

    QVector<uint8_t *> iData(iNPlanes);
    int iLineSize;

    if (av_samples_fill_arrays(&iData.data()[0],
                               &iLineSize,
                               (const uint8_t *) packet.buffer().data(),
                               iNChannels,
                               iNSamples,
                               iSampleFormat,
                               1) < 0)
        return;

    QbCaps caps1(packet.caps());
    QbCaps caps2(this->m_curInputCaps);

    caps1.setProperty("samples", QVariant());
    caps2.setProperty("samples", QVariant());

    if (caps1 != caps2)
    {
        // create resampler context
        this->m_resampleContext = SwrContextPtr(swr_alloc(), this->deleteSwrContext);

        if (!this->m_resampleContext)
            return;

        // set options
        av_opt_set_int(this->m_resampleContext.data(), "in_channel_layout", iChannelLayout, 0);
        av_opt_set_int(this->m_resampleContext.data(), "in_sample_rate", iSampleRate, 0);
        av_opt_set_sample_fmt(this->m_resampleContext.data(), "in_sample_fmt", iSampleFormat, 0);

        av_opt_set_int(this->m_resampleContext.data(), "out_channel_layout", oChannelLayout, 0);
        av_opt_set_int(this->m_resampleContext.data(), "out_sample_rate", oSampleRate, 0);
        av_opt_set_sample_fmt(this->m_resampleContext.data(), "out_sample_fmt", oSampleFormat, 0);

        // initialize the resampling context
        if (swr_init(this->m_resampleContext.data()) < 0)
            return;

        this->m_curInputCaps = packet.caps();
    }

    // compute destination number of samples
    int oNSamples = av_rescale_rnd(swr_get_delay(this->m_resampleContext.data(),
                                                 iSampleRate) +
                                   iNSamples,
                                   oSampleRate,
                                   iSampleRate,
                                   AV_ROUND_UP);

    // buffer is going to be directly written to a rawaudio file, no alignment
    int oNPlanes = av_sample_fmt_is_planar(oSampleFormat)? oNChannels: 1;
    QVector<uint8_t *> oData(oNPlanes);

    int oLineSize;

    int oBufferSize = av_samples_get_buffer_size(&oLineSize,
                                                 oNChannels,
                                                 oNSamples,
                                                 oSampleFormat,
                                                 1);

    QSharedPointer<uchar> oBuffer(new uchar[oBufferSize]);

    if (!oBuffer)
        return;

    if (av_samples_fill_arrays(&oData.data()[0],
                               &oLineSize,
                               (const uint8_t *) oBuffer.data(),
                               oNChannels,
                               oNSamples,
                               oSampleFormat,
                               1) < 0)
        return;

    // convert to destination format
    if (swr_convert(this->m_resampleContext.data(),
                    oData.data(),
                    oNSamples,
                    (const uint8_t **) iData.data(),
                    iNSamples) < 0)
        return;

    const char *format = av_get_sample_fmt_name(oSampleFormat);
    char layout[256];

    av_get_channel_layout_string(layout,
                                 sizeof(layout),
                                 oNChannels,
                                 oChannelLayout);

    QString caps = QString("audio/x-raw,"
                           "format=%1,"
                           "channels=%2,"
                           "rate=%3,"
                           "layout=%4,"
                           "samples=%5").arg(format)
                                        .arg(oNChannels)
                                        .arg(oSampleRate)
                                        .arg(layout)
                                        .arg(oNSamples);

    QbPacket oPacket(caps,
                     oBuffer,
                     oBufferSize);

    oPacket.setPts(packet.pts());
    oPacket.setDuration(packet.duration());
    oPacket.setTimeBase(packet.timeBase());
    oPacket.setIndex(packet.index());

    emit this->oStream(oPacket);
}
Beispiel #19
0
/**
 * Decode a frame to a packet, run the result through SwrContext, if desired, encode it via an appropriate
 * encoder, and write the results to the Java-side native buffer.
 *
 * @param aio       FFAudio context
 * @param cached    true or false
 * @return number of bytes placed into java buffer or a negative value, if something went wrong
 */
static int decode_packet(FFAudioIO *aio, int cached) {
    int res = 0;
    uint8_t **resample_buf = NULL;
    jobject byte_buffer = NULL;
    uint8_t *javaBuffer = NULL;
    uint32_t out_buf_size = 0;
    int out_buf_samples = 0;
    int64_t out_channel_count;
    int64_t out_sample_rate;
    int flush = aio->got_frame;
    enum AVSampleFormat out;
    int bytesConsumed = 0;

    init_ids(aio->env, aio->java_instance);

    av_opt_get_int(aio->swr_context, "out_channel_count", 0, &out_channel_count);
    av_opt_get_int(aio->swr_context, "out_sample_rate", 0, &out_sample_rate);
    av_opt_get_sample_fmt(aio->swr_context, "out_sample_fmt", 0, &out);

    resample_buf = av_mallocz(sizeof(uint8_t *) * 1); // one plane!

    // make sure we really have an audio packet
    if (aio->decode_packet.stream_index == aio->stream_index) {
        // decode frame
        // got_frame indicates whether we got a frame
        bytesConsumed = avcodec_decode_audio4(aio->decode_context, aio->decode_frame, &aio->got_frame, &aio->decode_packet);
        if (bytesConsumed < 0) {
            throwUnsupportedAudioFileExceptionIfError(aio->env, bytesConsumed, "Failed to decode audio frame.");
            return bytesConsumed;
        }

        if (aio->got_frame) {

            aio->decoded_samples += aio->decode_frame->nb_samples;
            out_buf_samples = aio->decode_frame->nb_samples;
#ifdef DEBUG
            fprintf(stderr, "samples%s n:%" PRIu64 " nb_samples:%d pts:%s\n",
                   cached ? "(cached)" : "",
                   aio->decoded_samples, aio->decode_frame->nb_samples,
                   av_ts2timestr(aio->decode_frame->pts, &aio->decode_context->time_base));
#endif

            // adjust out sample number for a different sample rate
            // this is an estimate!!
            out_buf_samples = av_rescale_rnd(
                    swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate) + aio->decode_frame->nb_samples,
                    out_sample_rate,
                    aio->stream->codecpar->sample_rate,
                    AV_ROUND_UP
            );

            // allocate new aio->audio_data buffers
            res = av_samples_alloc(aio->audio_data, NULL, av_frame_get_channels(aio->decode_frame),
                                   aio->decode_frame->nb_samples, aio->decode_frame->format, 1);
            if (res < 0) {
                throwIOExceptionIfError(aio->env, res, "Could not allocate audio buffer.");
                return AVERROR(ENOMEM);
            }
            // copy audio data to aio->audio_data
            av_samples_copy(aio->audio_data, aio->decode_frame->data, 0, 0,
                            aio->decode_frame->nb_samples, av_frame_get_channels(aio->decode_frame), aio->decode_frame->format);

            res = resample(aio, resample_buf, out_buf_samples, (const uint8_t **)aio->audio_data, aio->decode_frame->nb_samples);
            if (res < 0) goto bail;
            else out_buf_samples = res;

        } else if (flush && swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate)) {

            res = resample(aio, resample_buf, swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate), NULL, 0);
            if (res < 0) goto bail;
            else out_buf_samples = res;
        } else {
#ifdef DEBUG
            fprintf(stderr, "Got no frame.\n");
#endif
        }

        if (out_buf_samples > 0) {

            res =  av_samples_get_buffer_size(NULL, (int)out_channel_count, out_buf_samples, out, 1);
            if (res < 0) goto bail;
            else out_buf_size = res;

            // ensure native buffer capacity
            if (aio->java_buffer_capacity < out_buf_size) {
                aio->java_buffer_capacity = (*aio->env)->CallIntMethod(aio->env, aio->java_instance, setNativeBufferCapacity_MID, (jint)out_buf_size);
            }
            // get java-managed byte buffer reference
            byte_buffer = (*aio->env)->GetObjectField(aio->env, aio->java_instance, nativeBuffer_FID);
            if (!byte_buffer) {
                res = -1;
                throwIOExceptionIfError(aio->env, 1, "Failed to get native buffer.");
                goto bail;
            }

            // we have some samples, let's copy them to the java buffer, using the desired encoding
            javaBuffer = (uint8_t *)(*aio->env)->GetDirectBufferAddress(aio->env, byte_buffer);
            if (!javaBuffer) {
                throwIOExceptionIfError(aio->env, 1, "Failed to get address for native buffer.");
                goto bail;
            }
            if (aio->encode_context) {
                aio->encode_frame->nb_samples = out_buf_samples;
                res = encode_buffer(aio, resample_buf[0], out_buf_size, javaBuffer);
                if (res < 0) {
                    out_buf_size = 0;
                    goto bail;
                }
                out_buf_size = res;
            } else {
                memcpy(javaBuffer, resample_buf[0], out_buf_size);
            }
            // we already wrote to the buffer, now we still need to
            // set new bytebuffer limit and position to 0.
            (*aio->env)->CallObjectMethod(aio->env, byte_buffer, rewind_MID);
            (*aio->env)->CallObjectMethod(aio->env, byte_buffer, limit_MID, out_buf_size);
        }
    }

    aio->resampled_samples += out_buf_size;

bail:

    if (resample_buf) {
        if (resample_buf[0]) av_freep(&resample_buf[0]);
        av_free(resample_buf);
    }
    if (aio->audio_data[0]) av_freep(&aio->audio_data[0]);

    return res;
}
std::int64_t Swr::GetDelay(std::int64_t base)
{
	assert(this->context != nullptr);
	return swr_get_delay(this->context, base);
}
Beispiel #21
0
static void write_audio_frame(AVFormatContext *oc, AVStream *st, int flush)
{
    AVCodecContext *c;
    AVPacket pkt = { 0 }; // data and size must be 0;
    int got_packet, ret, dst_nb_samples;

    av_init_packet(&pkt);
    c = st->codec;

    if (!flush) {
        get_audio_frame((int16_t *)src_samples_data[0], src_nb_samples, c->channels);

        /* convert samples from native format to destination codec format, using the resampler */
        if (swr_ctx) {
            /* compute destination number of samples */
            dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + src_nb_samples,
                                            c->sample_rate, c->sample_rate, AV_ROUND_UP);
            if (dst_nb_samples > max_dst_nb_samples) {
                av_free(dst_samples_data[0]);
                ret = av_samples_alloc(dst_samples_data, &dst_samples_linesize, c->channels,
                                       dst_nb_samples, c->sample_fmt, 0);
                if (ret < 0)
                    exit(1);
                max_dst_nb_samples = dst_nb_samples;
                dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples,
                                                              c->sample_fmt, 0);
            }

            /* convert to destination format */
            ret = swr_convert(swr_ctx,
                              dst_samples_data, dst_nb_samples,
                              (const uint8_t **)src_samples_data, src_nb_samples);
            if (ret < 0) {
                fprintf(stderr, "Error while converting\n");
                exit(1);
            }
        } else {
            dst_nb_samples = src_nb_samples;
        }

        audio_frame->nb_samples = dst_nb_samples;
        audio_frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base);
        avcodec_fill_audio_frame(audio_frame, c->channels, c->sample_fmt,
                                 dst_samples_data[0], dst_samples_size, 0);
        samples_count += dst_nb_samples;
    }

    ret = avcodec_encode_audio2(c, &pkt, flush ? NULL : audio_frame, &got_packet);
    if (ret < 0) {
        fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
        exit(1);
    }

    if (!got_packet) {
        if (flush)
            audio_is_eof = 1;
        return;
    }

    ret = write_frame(oc, &c->time_base, st, &pkt);
    if (ret < 0) {
        fprintf(stderr, "Error while writing audio frame: %s\n",
                av_err2str(ret));
        exit(1);
    }
}
Beispiel #22
0
static int get_delay(struct af_resample *s)
{
    return swr_get_delay(s->avrctx, s->ctx.in_rate);
}
int decode_frame_from_packet(State *state, AVPacket *aPacket, int *frame_size_ptr, int from_thread)
{
	int n;
	int16_t *samples;
	AVPacket *pkt = aPacket;
    AVFrame *decoded_frame = NULL;
    int got_frame = 0;
    
	int64_t src_ch_layout, dst_ch_layout;
	int src_rate, dst_rate;
	uint8_t **src_data = NULL, **dst_data = NULL;
	int src_nb_channels = 0, dst_nb_channels = 0;
	int src_linesize, dst_linesize;
	int src_nb_samples, dst_nb_samples, max_dst_nb_samples;
	enum AVSampleFormat src_sample_fmt, dst_sample_fmt;
	int dst_bufsize;
	const char *fmt;
	struct SwrContext *swr_ctx;
	double t;
    int ret;

    if (aPacket->stream_index == state->audio_stream) {
        	
    	if (!decoded_frame) {
    		if (!(decoded_frame = avcodec_alloc_frame())) {
    			__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate audio frame\n");
    	        return -2;
    		}
    	}
    	
    	if (avcodec_decode_audio4(state->audio_st->codec, decoded_frame, &got_frame, aPacket) < 0) {
    		__android_log_print(ANDROID_LOG_ERROR, "TAG", "avcodec_decode_audio4() decoded no frame");
    		return -2;
    	}
    	
    	int data_size = 0;
    	
    	if (got_frame) {
    		/* if a frame has been decoded, output it */
    		data_size = av_samples_get_buffer_size(NULL, state->audio_st->codec->channels,
    	    		decoded_frame->nb_samples,
    	    		state->audio_st->codec->sample_fmt, 1);
    	} else {
    		*frame_size_ptr = 0;
    	    return 0;
    	}
    	
        if (decoded_frame->format != AV_SAMPLE_FMT_S16) {
            src_nb_samples = decoded_frame->nb_samples;
            src_linesize = (int) decoded_frame->linesize;
            src_data = decoded_frame->data;
            
            if (decoded_frame->channel_layout == 0) {
            	decoded_frame->channel_layout = av_get_default_channel_layout(decoded_frame->channels);
            }
            
            /* create resampler context */
            swr_ctx = swr_alloc();
            if (!swr_ctx) {
            	//fprintf(stderr, "Could not allocate resampler context\n");
                //ret = AVERROR(ENOMEM);
                //goto end;
            }
            
            src_rate = decoded_frame->sample_rate;
            dst_rate = decoded_frame->sample_rate;
            src_ch_layout = decoded_frame->channel_layout;
            dst_ch_layout = decoded_frame->channel_layout;
            src_sample_fmt = decoded_frame->format;
            dst_sample_fmt = AV_SAMPLE_FMT_S16;
            
            av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
            av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout,  0);
            av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
            av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
            av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
            av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt,  0);
            
            /* initialize the resampling context */
            if ((ret = swr_init(swr_ctx)) < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Failed to initialize the resampling context\n");
            	//goto end;
            }

            /* allocate source and destination samples buffers */

            src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
            ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels,
            		src_nb_samples, src_sample_fmt, 0);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate source samples\n");
            	//goto end;
            }

            /* compute the number of converted samples: buffering is avoided
             * ensuring that the output buffer will contain at least all the
             * converted input samples */
            max_dst_nb_samples = dst_nb_samples =
            	av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

            /* buffer is going to be directly written to a rawaudio file, no alignment */
            dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
            ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
            		dst_nb_samples, dst_sample_fmt, 0);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Could not allocate destination samples\n");
            	//goto end;
            }
            
            /* compute destination number of samples */
            dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) +
                                            src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
            
            /* convert to destination format */
            ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame->data, src_nb_samples);
            if (ret < 0) {
            	__android_log_print(ANDROID_LOG_INFO, "TAG", "Error while converting\n");
                //goto end;
            }
            dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                     ret, dst_sample_fmt, 1);
            if (dst_bufsize < 0) {
                fprintf(stderr, "Could not get sample buffer size\n");
                //goto end;
            }
            
            samples = malloc(dst_bufsize);
    		memcpy(samples, dst_data[0], dst_bufsize);
    		data_size = dst_bufsize;
    		swr_free(&swr_ctx);
    	} else {
    		/* if a frame has been decoded, output it */
    	    data_size = av_samples_get_buffer_size(NULL, state->audio_st->codec->channels,
    	    		decoded_frame->nb_samples, state->audio_st->codec->sample_fmt, 1);
    		samples = malloc(data_size);
    		memcpy(samples, decoded_frame->data[0], data_size);
    	}
        
        *frame_size_ptr = data_size;
        
        // TODO add this call back!
        //*pts_ptr = pts;
        n = 2 * state->audio_st->codec->channels;
        state->audio_clock += (double)*frame_size_ptr /
        		(double)(n * state->audio_st->codec->sample_rate);

        /* if update, update the audio clock w/pts */
        if(pkt->pts != AV_NOPTS_VALUE) {
        	state->audio_clock = av_q2d(state->audio_st->time_base) * pkt->pts;
        }
    	
        //*frame_size_ptr = data_size;
        state->write_audio_callback(state->clazz, samples, data_size, from_thread);
        
    	avcodec_free_frame(&decoded_frame);
        
        free(samples);
        
    	return AUDIO_DATA_ID;
    }

    return 0;
}
void cAudio::run()
{
	lt_info("====================== start decoder thread ================================\n");
	/* libavcodec & friends */
	av_register_all();

	AVCodec *codec;
	AVFormatContext *avfc = NULL;
	AVInputFormat *inp;
	AVFrame *frame;
	uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE);
	AVPacket avpkt;
	int ret, driver;
	/* libao */
	ao_info *ai;
	// ao_device *adevice;
	// ao_sample_format sformat;
	/* resample */
	SwrContext *swr = NULL;
	uint8_t *obuf = NULL;
	int obuf_sz = 0; /* in samples */
	int obuf_sz_max = 0;
	int o_ch, o_sr; /* output channels and sample rate */
	uint64_t o_layout; /* output channels layout */
	char tmp[64] = "unknown";

	curr_pts = 0;
	av_init_packet(&avpkt);
	inp = av_find_input_format("mpegts");
	AVIOContext *pIOCtx = avio_alloc_context(inbuf, INBUF_SIZE, // internal Buffer and its size
			0,		// bWriteable (1=true,0=false)
			NULL,		// user data; will be passed to our callback functions
			_my_read,	// read callback
			NULL,		// write callback
			NULL);		// seek callback
	avfc = avformat_alloc_context();
	avfc->pb = pIOCtx;
	avfc->iformat = inp;
	avfc->probesize = 188*5;
	thread_started = true;

	if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) {
		lt_info("%s: avformat_open_input() failed.\n", __func__);
		goto out;
	}
	ret = avformat_find_stream_info(avfc, NULL);
	lt_debug("%s: avformat_find_stream_info: %d\n", __func__, ret);
	if (avfc->nb_streams != 1)
	{
		lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams);
		goto out;
	}
	if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
		lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);

	c = avfc->streams[0]->codec;
	codec = avcodec_find_decoder(c->codec_id);
	if (!codec) {
		lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id));
		goto out;
	}
	if (avcodec_open2(c, codec, NULL) < 0) {
		lt_info("%s: avcodec_open2() failed\n", __func__);
		goto out;
	}
	frame = av_frame_alloc();
	if (!frame) {
		lt_info("%s: avcodec_alloc_frame failed\n", __func__);
		goto out2;
	}
	/* output sample rate, channels, layout could be set here if necessary */
	o_ch = c->channels;		/* 2 */
	o_sr = c->sample_rate;		/* 48000 */
	o_layout = c->channel_layout;	/* AV_CH_LAYOUT_STEREO */
	if (sformat.channels != o_ch || sformat.rate != o_sr ||
	    sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL)
	{
		driver = ao_default_driver_id();
		sformat.bits = 16;
		sformat.channels = o_ch;
		sformat.rate = o_sr;
		sformat.byte_format = AO_FMT_NATIVE;
		sformat.matrix = 0;
		if (adevice)
			ao_close(adevice);
		adevice = ao_open_live(driver, &sformat, NULL);
		ai = ao_driver_info(driver);
		lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n",
			__func__, o_ch, o_sr, 16, adevice);;
		lt_info("libao driver: %d name '%s' short '%s' author '%s'\n",
				driver, ai->name, ai->short_name, ai->author);
	}
#if 0
	lt_info(" driver options:");
	for (int i = 0; i < ai->option_count; ++i)
		fprintf(stderr, " %s", ai->options[i]);
	fprintf(stderr, "\n");
#endif
	av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt);
	lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n",
		 avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels);
	swr = swr_alloc_set_opts(swr,
				 o_layout, AV_SAMPLE_FMT_S16, o_sr,			/* output */
				 c->channel_layout, c->sample_fmt, c->sample_rate,	/* input */
				 0, NULL);
	if (! swr) {
		lt_info("could not alloc resample context\n");
		goto out3;
	}
	swr_init(swr);
	while (thread_started) {
		int gotframe = 0;
		if (av_read_frame(avfc, &avpkt) < 0)
			break;
		avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
		if (gotframe && thread_started) {
			int out_linesize;
			obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) +
						 frame->nb_samples, o_sr, c->sample_rate, AV_ROUND_UP);
			if (obuf_sz > obuf_sz_max) {
				lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max);
				av_free(obuf);
				if (av_samples_alloc(&obuf, &out_linesize, o_ch,
							frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) {
					lt_info("av_samples_alloc failed\n");
					av_free_packet(&avpkt);
					break; /* while (thread_started) */
				}
				obuf_sz_max = obuf_sz;
			}
			obuf_sz = swr_convert(swr, &obuf, obuf_sz,
					      (const uint8_t **)frame->extended_data, frame->nb_samples);
			curr_pts = av_frame_get_best_effort_timestamp(frame);
			lt_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0);
			int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch,
								  obuf_sz, AV_SAMPLE_FMT_S16, 1);
			ao_play(adevice, (char *)obuf, o_buf_sz);
		}
		av_free_packet(&avpkt);
	}
	// ao_close(adevice); /* can take long :-( */
	av_free(obuf);
	swr_free(&swr);
 out3:
	av_frame_free(&frame);
 out2:
	avcodec_close(c);
	c = NULL;
 out:
	avformat_close_input(&avfc);
	av_free(pIOCtx->buffer);
	av_free(pIOCtx);
	lt_info("======================== end decoder thread ================================\n");
}
long audio_tutorial_resample(VideoState *is, struct AVFrame *inframe) {

#ifdef __RESAMPLER__

#ifdef __LIBAVRESAMPLE__

// There is pre 1.0 libavresample and then there is above..
#if LIBAVRESAMPLE_VERSION_MAJOR == 0
    void **resample_input_bytes = (void **)inframe->extended_data;
#else
    uint8_t **resample_input_bytes = (uint8_t **)inframe->extended_data;
#endif

#else
    uint8_t **resample_input_bytes = (uint8_t **)inframe->extended_data;
#endif


    int resample_nblen = 0;
    long resample_long_bytes = 0;

    if( is->pResampledOut == NULL || inframe->nb_samples > is->resample_size) {
        
#if __LIBAVRESAMPLE__
        is->resample_size = av_rescale_rnd(avresample_get_delay(is->pSwrCtx) +
                                           inframe->nb_samples,
                                           44100,
                                           44100,
                                           AV_ROUND_UP);
#else
        is->resample_size = av_rescale_rnd(swr_get_delay(is->pSwrCtx,
                                           44100) +
                                           inframe->nb_samples,
                                           44100,
                                           44100,
                                           AV_ROUND_UP);
#endif

        if(is->pResampledOut != NULL) {
            av_free(is->pResampledOut);
            is->pResampledOut = NULL;
        }

        av_samples_alloc(&is->pResampledOut, &is->resample_lines, 2, is->resample_size,
                         AV_SAMPLE_FMT_S16, 0);

    }


#ifdef __LIBAVRESAMPLE__

// OLD API (0.0.3) ... still NEW API (1.0.0 and above).. very frustrating..
// USED IN FFMPEG 1.0 (LibAV SOMETHING!). New in FFMPEG 1.1 and libav 9
#if LIBAVRESAMPLE_VERSION_INT <= 3
    // AVResample OLD
    resample_nblen = avresample_convert(is->pSwrCtx, (void **)&is->pResampledOut, 0,
                                        is->resample_size,
                                        (void **)resample_input_bytes, 0, inframe->nb_samples);
#else
    //AVResample NEW
    resample_nblen = avresample_convert(is->pSwrCtx, (uint8_t **)&is->pResampledOut,
                                        0, is->resample_size,
                                        (uint8_t **)resample_input_bytes, 0, inframe->nb_samples);
#endif

#else
    // SWResample
    resample_nblen = swr_convert(is->pSwrCtx, (uint8_t **)&is->pResampledOut,
                                 is->resample_size,
                                 (const uint8_t **)resample_input_bytes, inframe->nb_samples);
#endif

    resample_long_bytes = av_samples_get_buffer_size(NULL, 2, resample_nblen,
                         AV_SAMPLE_FMT_S16, 1);

    if (resample_nblen < 0) {
        fprintf(stderr, "reSample to another sample format failed!\n");
        return -1;
    }

    return resample_long_bytes;

#else
    return -1;
#endif
}
Beispiel #26
0
int procAudioResampling(AVCodecContext * audio_dec_ctx,
	AVFrame * pAudioDecodeFrame,
	int out_sample_fmt,
	int out_channels,
	int out_sample_rate,
	uint8_t * audio_chunk)
{
	SwrContext * swr_ctx = NULL;
	int data_size = 0;
	int ret = 0;
	int64_t src_ch_layout = audio_dec_ctx->channel_layout;
	int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
	int dst_nb_channels = 0;
	int dst_linesize = 0;
	int src_nb_samples = 0;
	int dst_nb_samples = 0;
	int max_dst_nb_samples = 0;
	uint8_t **dst_data = NULL;
	int resampled_data_size = 0;

	swr_ctx = swr_alloc();
	if (!swr_ctx)
	{
		LOGD("swr_alloc error \n");
		return -1;
	}

	src_ch_layout = (audio_dec_ctx->channels ==
		av_get_channel_layout_nb_channels(audio_dec_ctx->channel_layout)) ?
		audio_dec_ctx->channel_layout :
		av_get_default_channel_layout(audio_dec_ctx->channels);

	if (out_channels == 1)
	{
		dst_ch_layout = AV_CH_LAYOUT_MONO;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_MONO\n");
	}
	else if (out_channels == 2)
	{
		dst_ch_layout = AV_CH_LAYOUT_STEREO;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_STEREO\n");
	}
	else
	{
		dst_ch_layout = AV_CH_LAYOUT_SURROUND;
		//LOGD("dst_ch_layout: AV_CH_LAYOUT_SURROUND\n");
	}

	if (src_ch_layout <= 0)
	{
		LOGD("src_ch_layout error \n");
		return -1;
	}

	src_nb_samples = pAudioDecodeFrame->nb_samples;
	if (src_nb_samples <= 0)
	{
		LOGD("src_nb_samples error \n");
		return -1;
	}

	av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
	av_opt_set_int(swr_ctx, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
	av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);

	av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
	av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
	av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", (AVSampleFormat)out_sample_fmt, 0);

	if ((ret = swr_init(swr_ctx)) < 0) {
		LOGD("Failed to initialize the resampling context\n");
		return -1;
	}

	max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples,
		out_sample_rate, audio_dec_ctx->sample_rate, AV_ROUND_UP);
	if (max_dst_nb_samples <= 0)
	{
		LOGD("av_rescale_rnd error \n");
		return -1;
	}

	dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
	ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
		dst_nb_samples, (AVSampleFormat)out_sample_fmt, 0);
	if (ret < 0)
	{
		LOGD("av_samples_alloc_array_and_samples error \n");
		return -1;
	}


	dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, audio_dec_ctx->sample_rate) +
		src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate, AV_ROUND_UP);
	if (dst_nb_samples <= 0)
	{
		LOGD("av_rescale_rnd error \n");
		return -1;
	}
	if (dst_nb_samples > max_dst_nb_samples)
	{
		av_free(dst_data[0]);
		ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
			dst_nb_samples, (AVSampleFormat)out_sample_fmt, 1);
		max_dst_nb_samples = dst_nb_samples;
	}

	if (swr_ctx)
	{
		ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
			(const uint8_t **)pAudioDecodeFrame->data, pAudioDecodeFrame->nb_samples);
		if (ret < 0)
		{
			LOGD("swr_convert error \n");
			return -1;
		}

		resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
			ret, (AVSampleFormat)out_sample_fmt, 1);
		if (resampled_data_size < 0)
		{
			LOGD("av_samples_get_buffer_size error \n");
			return -1;
		}
	}
	else
	{
		LOGD("swr_ctx null error \n");
		return -1;
	}

	//LOGD("resampled_data_size:%d",resampled_data_size);
	memcpy(audio_chunk, dst_data[0], resampled_data_size);

	if (dst_data)
	{
		av_freep(&dst_data[0]);
	}
	av_freep(&dst_data);
	dst_data = NULL;

	if (swr_ctx)
	{
		swr_free(&swr_ctx);
	}
	return resampled_data_size;
}
int audioResampling(AVCodecContext *audio_dec_ctx, AVFrame *pAudioDecodeFrame,
                    int out_sample_fmt, int out_channels, int out_sample_rate, char *out_buf) {
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12");
    SwrContext *swr_ctx = NULL;
    int data_size = 0;
    int ret = 0;
    int64_t src_ch_layout = AV_CH_LAYOUT_STEREO; //初始化这样根据不同文件做调整
    int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO; //这里设定ok
    int dst_nb_channels = 0;
    int dst_linesize = 0;
    int src_nb_samples = 0;
    int dst_nb_samples = 0;
    int max_dst_nb_samples = 0;
    uint8_t **dst_data = NULL;
    int resampled_data_size = 0;
    //重新采样
    if (swr_ctx) {
        swr_free(&swr_ctx);
    }
    swr_ctx = swr_alloc();
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-1");
    if (!swr_ctx) {
        printf("swr_alloc error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream13");
        return -1;
    }

    src_ch_layout = (audio_dec_ctx->channel_layout &&
                     audio_dec_ctx->channels ==
                     av_get_channel_layout_nb_channels(audio_dec_ctx->channel_layout)) ?
                    audio_dec_ctx->channel_layout :
                    av_get_default_channel_layout(audio_dec_ctx->channels);
    if (out_channels == 1) {
        dst_ch_layout = AV_CH_LAYOUT_MONO;
    }
    else if (out_channels == 2) {
        dst_ch_layout = AV_CH_LAYOUT_STEREO;
    }
    else {
        //可扩展
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-2");
    if (src_ch_layout <= 0) {
        printf("src_ch_layout error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream14");
        return -1;
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream12-3");
    src_nb_samples = pAudioDecodeFrame->nb_samples;
    if (src_nb_samples <= 0) {
        printf("src_nb_samples error \n");
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "stream15");
        return -1;
    }

    /* set options */
    av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
    av_opt_set_int(swr_ctx, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);

    av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
    av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", (AVSampleFormat) out_sample_fmt, 0);
    swr_init(swr_ctx);
    max_dst_nb_samples = dst_nb_samples =
            av_rescale_rnd(src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate,
                           AV_ROUND_UP);
    if (max_dst_nb_samples <= 0) {
        printf("av_rescale_rnd error \n");
        return -1;
    }

    dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
    ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
                                             dst_nb_samples, (AVSampleFormat) out_sample_fmt, 0);
    if (ret < 0) {
        printf("av_samples_alloc_array_and_samples error \n");
        return -1;
    }


    dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, audio_dec_ctx->sample_rate) +
                                    src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate,
                                    AV_ROUND_UP);
    if (dst_nb_samples <= 0) {
        return -1;
    }
    if (dst_nb_samples > max_dst_nb_samples) {
        av_free(dst_data[0]);
        ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
                               dst_nb_samples, (AVSampleFormat) out_sample_fmt, 1);
        max_dst_nb_samples = dst_nb_samples;
    }
    data_size = av_samples_get_buffer_size(NULL, audio_dec_ctx->channels,
                                           pAudioDecodeFrame->nb_samples,
                                           audio_dec_ctx->sample_fmt, 1);
    if (data_size <= 0) {
        return -1;
    }
    resampled_data_size = data_size;
    if (swr_ctx) {
        ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
                          (const uint8_t **) pAudioDecodeFrame->data,
                          pAudioDecodeFrame->nb_samples);
        if (ret <= 0) {
            return -1;
        }

        resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                         ret, (AVSampleFormat) out_sample_fmt, 1);
        if (resampled_data_size <= 0) {
            return -1;
        }
    }
    else {
        return -1;
    }
    //将值返回去
    memcpy(out_buf, dst_data[0], resampled_data_size);
    if (dst_data) {
        av_freep(&dst_data[0]);
    }
    av_freep(&dst_data);
    dst_data = NULL;

    if (swr_ctx) {
        swr_free(&swr_ctx);
    }
    return resampled_data_size;
}
int decode_frame_from_packet(VideoState *is, AVFrame decoded_frame)
{
	int64_t src_ch_layout, dst_ch_layout;
	int src_rate, dst_rate;
	uint8_t **src_data = NULL, **dst_data = NULL;
	int src_nb_channels = 0, dst_nb_channels = 0;
	int src_linesize, dst_linesize;
	int src_nb_samples, dst_nb_samples, max_dst_nb_samples;
	enum AVSampleFormat src_sample_fmt, dst_sample_fmt;
	int dst_bufsize;
	int ret;

	src_nb_samples = decoded_frame.nb_samples;
	src_linesize = (int) decoded_frame.linesize;
	src_data = decoded_frame.data;

	if (decoded_frame.channel_layout == 0) {
		decoded_frame.channel_layout = av_get_default_channel_layout(decoded_frame.channels);
	}

	src_rate = decoded_frame.sample_rate;
	dst_rate = decoded_frame.sample_rate;
	src_ch_layout = decoded_frame.channel_layout;
	dst_ch_layout = decoded_frame.channel_layout;
	src_sample_fmt = decoded_frame.format;
	dst_sample_fmt = AV_SAMPLE_FMT_S16;

	av_opt_set_int(is->sws_ctx_audio, "in_channel_layout", src_ch_layout, 0);
	av_opt_set_int(is->sws_ctx_audio, "out_channel_layout", dst_ch_layout,  0);
	av_opt_set_int(is->sws_ctx_audio, "in_sample_rate", src_rate, 0);
	av_opt_set_int(is->sws_ctx_audio, "out_sample_rate", dst_rate, 0);
	av_opt_set_sample_fmt(is->sws_ctx_audio, "in_sample_fmt", src_sample_fmt, 0);
	av_opt_set_sample_fmt(is->sws_ctx_audio, "out_sample_fmt", dst_sample_fmt,  0);

	/* initialize the resampling context */
	if ((ret = swr_init(is->sws_ctx_audio)) < 0) {
		fprintf(stderr, "Failed to initialize the resampling context\n");
		return -1;
	}

	/* allocate source and destination samples buffers */
	src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
	ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");
		return -1;
	}

	/* compute the number of converted samples: buffering is avoided
	 * ensuring that the output buffer will contain at least all the
	 * converted input samples */
	max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

	/* buffer is going to be directly written to a rawaudio file, no alignment */
	dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
	ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate destination samples\n");
		return -1;
	}

	/* compute destination number of samples */
	dst_nb_samples = av_rescale_rnd(swr_get_delay(is->sws_ctx_audio, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

	/* convert to destination format */
	ret = swr_convert(is->sws_ctx_audio, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame.data, src_nb_samples);
	if (ret < 0) {
		fprintf(stderr, "Error while converting\n");
		return -1;
	}

	dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, ret, dst_sample_fmt, 1);
	if (dst_bufsize < 0) {
		fprintf(stderr, "Could not get sample buffer size\n");
		return -1;
	}

	memcpy(is->audio_buf, dst_data[0], dst_bufsize);

	if (src_data) {
		av_freep(&src_data[0]);
	}
	av_freep(&src_data);

	if (dst_data) {
		av_freep(&dst_data[0]);
	}
	av_freep(&dst_data);

	return dst_bufsize;
}
Beispiel #29
0
static double get_delay(struct af_resample *s)
{
    int64_t base = s->in_rate * (int64_t)s->out_rate;
    return swr_get_delay(s->avrctx, base) / (double)base;
}
Beispiel #30
0
QbPacket ConvertAudio::convert(const QbAudioPacket &packet,
                               const QbCaps &oCaps)
{
    QbAudioCaps oAudioCaps(oCaps);

    int64_t iSampleLayout = channelLayouts->value(packet.caps().layout(), 0);
    AVSampleFormat iSampleFormat = sampleFormats->value(packet.caps().format(),
                                                        AV_SAMPLE_FMT_NONE);
    int iSampleRate = packet.caps().rate();
    int iNChannels = packet.caps().channels();
    int iNSamples = packet.caps().samples();

    int64_t oSampleLayout = channelLayouts->value(oAudioCaps.layout(),
                                                  AV_CH_LAYOUT_STEREO);
    AVSampleFormat oSampleFormat = sampleFormats->value(oAudioCaps.format(),
                                                        AV_SAMPLE_FMT_FLT);
    int oSampleRate = oAudioCaps.rate();
    int oNChannels = oAudioCaps.channels();

    this->m_resampleContext =
            swr_alloc_set_opts(this->m_resampleContext,
                               oSampleLayout,
                               oSampleFormat,
                               oSampleRate,
                               iSampleLayout,
                               iSampleFormat,
                               iSampleRate,
                               0,
                               NULL);

    if (!this->m_resampleContext)
        return QbPacket();

    if (!swr_is_initialized(this->m_resampleContext))
        if (swr_init(this->m_resampleContext) < 0)
            return QbPacket();

    // Create input audio frame.
    static AVFrame iFrame;
    memset(&iFrame, 0, sizeof(AVFrame));

    if (av_samples_fill_arrays(iFrame.data,
                               iFrame.linesize,
                               (const uint8_t *) packet.buffer().data(),
                               iNChannels,
                               iNSamples,
                               iSampleFormat,
                               1) < 0)
        return QbPacket();

    iFrame.channels = iNChannels;
    iFrame.channel_layout = iSampleLayout;
    iFrame.format = iSampleFormat;
    iFrame.sample_rate = iSampleRate;
    iFrame.nb_samples = iNSamples;
    iFrame.pts = iFrame.pkt_pts = packet.pts();

    // Create output audio packet.
    int oNSamples = swr_get_delay(this->m_resampleContext, oSampleRate)
                    + iFrame.nb_samples
                    * (int64_t) oSampleRate
                    / iSampleRate
                    + 3;

    int oLineSize;
    int oBufferSize = av_samples_get_buffer_size(&oLineSize,
                                                 oNChannels,
                                                 oNSamples,
                                                 oSampleFormat,
                                                 1);

    QByteArray oBuffer(oBufferSize, Qt::Uninitialized);

    int oNPlanes = av_sample_fmt_is_planar(oSampleFormat)? oNChannels: 1;
    QVector<uint8_t *> oData(oNPlanes);

    if (av_samples_fill_arrays(&oData.data()[0],
                               &oLineSize,
                               (const uint8_t *) oBuffer.data(),
                               oNChannels,
                               oNSamples,
                               oSampleFormat,
                               1) < 0)
        return QbPacket();

    int64_t oPts = swr_next_pts(this->m_resampleContext, iFrame.pts);

    // convert to destination format
    int outputSamples = swr_convert(this->m_resampleContext,
                                    oData.data(),
                                    oNSamples,
                                    (const uint8_t **) iFrame.data,
                                    iFrame.nb_samples);

    if (outputSamples < 1)
        return QbPacket();

    oBufferSize = oBufferSize * outputSamples / oNSamples;

    QbBufferPtr buffer(new char[oBufferSize]);
    memcpy(buffer.data(), oBuffer.data(), oBufferSize);

    QbAudioPacket oAudioPacket;
    oAudioPacket.caps() = oAudioCaps;
    oAudioPacket.caps().samples() = outputSamples;
    oAudioPacket.buffer() = buffer;
    oAudioPacket.bufferSize() = oBufferSize;
    oAudioPacket.pts() = oPts;
    oAudioPacket.timeBase() = QbFrac(1, oAudioCaps.rate());
    oAudioPacket.index() = packet.index();
    oAudioPacket.id() = packet.id();

    return oAudioPacket.toPacket();
}