int audio_thr(LPVOID lpParam)
{
	int iRet = -1;
	//音频测试,播放文件显示波形
	AVFormatContext		*	pFmtCtx = NULL;
	AVFormatContext		*	pFOutmtCtx = NULL;
	AVInputFormat		*	pAudioInputFmt = NULL;
	AVOutputFormat		*	pAudioOutputFmt = NULL;
	AVCodecContext		*	pOutputCodecCtx = NULL;
	AVPacket				*	pAudioPacket = NULL;
	int						iAudioIndex = -1;
	int						data_size = 0;
	int						resampled_data_size = 0;
	uint8_t				*	out_buffer = 0;
	int64_t					dec_channel_layout = 0;
	double					pts;

	CLS_DlgStreamPusher* pThis = (CLS_DlgStreamPusher*)lpParam;
	if (pThis == NULL || pThis->m_pStreamInfo == NULL){
		TRACE("audio_thr--pThis == NULL || pThis->m_pStreamInfo == NULL\n");
		return iRet;
	}

	struct_stream_info* strct_stream_info = pThis->m_pStreamInfo;

	pAudioInputFmt = av_find_input_format("dshow");
	if (pAudioInputFmt == NULL){
		TRACE("pAudioInputFmt == NULL\n");
		return iRet;
	}

	char* psDevName = pThis->GetDeviceName(n_Audio);
	if (psDevName == NULL){
		TRACE("audio_thr--psDevName == NULL");
		return iRet;
	}

	if (avformat_open_input(&pFmtCtx, psDevName, pAudioInputFmt, NULL) != 0){
		TRACE("avformat_open_input err!\n");
		goto END;
	}
	if (avformat_find_stream_info(pFmtCtx, NULL) < 0){
		TRACE("avformat_find_stream_info(pFmtCtx, NULL) < 0\n");
		goto END;
	}

	for (int i = 0; i < pFmtCtx->nb_streams; i++){
		if (pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){
			iAudioIndex = i;
			AVCodec *tmpCodec = avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id);
			if (0 > avcodec_open2(pFmtCtx->streams[i]->codec, tmpCodec, NULL)){
				TRACE("can not find or open decoder!\n");
			}
			break;
		}
	}

	//找到音频流信息
	strct_stream_info->m_pAudioStream = pFmtCtx->streams[iAudioIndex];
	if (strct_stream_info->m_pAudioStream == NULL){
		TRACE("strct_stream_info->m_pAudioStream == NULL\n");
		goto END;
	}

	AVCodecContext *pAudioDec = strct_stream_info->m_pAudioStream->codec;
	if (NULL == pAudioDec){
		TRACE("NULL == pAudioDec\n");
		goto END;
	}

	AVCodec* audio_encoder = avcodec_find_encoder(AV_CODEC_ID_AAC);
	if (audio_encoder == NULL){
		TRACE("audio_encoder == NULL\r\n");
		goto END;
	}

	pOutputCodecCtx = avcodec_alloc_context3(audio_encoder);
	if (pOutputCodecCtx == NULL){
		TRACE("pOutputCodecCtx == NULL");
		goto END;
	}

	pOutputCodecCtx->sample_rate = pFmtCtx->streams[0]->codec->sample_rate;
	pOutputCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
	pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout);
	pOutputCodecCtx->sample_fmt = audio_encoder->sample_fmts[0];
	pOutputCodecCtx->codec = audio_encoder;
	pOutputCodecCtx->codec_tag = 0;
	if (avcodec_open2(pOutputCodecCtx, pOutputCodecCtx->codec, 0) < 0){
		//编码器打开失败,退出程序
		TRACE("音频编码器打开失败!\n");
		goto END;
	}

	//SDL_AudioSpec
	int out_nb_samples = AUDIO_BUF_SIZE;
	AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
	int out_buffer_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels, out_nb_samples, out_sample_fmt, 1);
	SDL_AudioSpec wanted_spec, spec;
	wanted_spec.freq = pOutputCodecCtx->sample_rate;
	wanted_spec.format = AUDIO_S16SYS;
	wanted_spec.channels = pOutputCodecCtx->channels;
	wanted_spec.silence = 0;
	wanted_spec.samples = out_nb_samples;
	wanted_spec.callback = fill_audio;//&CLS_DlgStreamPusher::
	wanted_spec.userdata = strct_stream_info;
	strct_stream_info->m_content_out_channels = pOutputCodecCtx->channels;

	if (SDL_OpenAudio(&wanted_spec, &spec)<0){
		TRACE("can't open audio.\n");
		goto END;
	}

	int audio_hw_buf_size = spec.size;
	if (audio_hw_buf_size < 0){
		TRACE("audio_hw_buf_size < 0\n");
		return -1;
	}
	strct_stream_info->m_audio_src.fmt = AV_SAMPLE_FMT_S16;
	strct_stream_info->m_audio_src.freq = spec.freq;
	strct_stream_info->m_audio_src.channel_layout = pOutputCodecCtx->channel_layout;
	strct_stream_info->m_audio_src.channels = spec.channels;
	strct_stream_info->m_audio_hw_buf_size = audio_hw_buf_size;
	strct_stream_info->m_audio_tgt = strct_stream_info->m_audio_src;

	AVPacket pkt;
	out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);

	strct_stream_info->m_audio_refresh_tid = SDL_CreateThread(audio_refresh_thread, NULL, strct_stream_info);

	while (av_read_frame(pFmtCtx, &pkt) == 0 && _kbhit() == 0){
		if (!pThis->m_blAudioShow){
			break;
		}
		if (pkt.stream_index != iAudioIndex){
			continue;
		}
		if (!strct_stream_info->m_pAudioFrame) {
			if (!(strct_stream_info->m_pAudioFrame = avcodec_alloc_frame())){
				TRACE("!(strct_stream_info->m_pAudioFrame = avcodec_alloc_frame())\n");
				goto END;
			}
		}
		else{
			avcodec_get_frame_defaults(strct_stream_info->m_pAudioFrame);
		}

		int gotframe = -1;
		strct_stream_info->m_pAudioFrame = av_frame_alloc();
		if (avcodec_decode_audio4(pAudioDec, strct_stream_info->m_pAudioFrame, &gotframe, &pkt) < 0){
			av_frame_free(&strct_stream_info->m_pAudioFrame);
			TRACE("can not decoder a frame\n");
			break;
		}
		av_free_packet(&pkt);

		if (!gotframe){
			//没有获取到数据,继续下一次
			continue;
		}
		strct_stream_info->m_pAudioFrame->nb_samples = 1024;//这里暂时写死值
		data_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels,
			strct_stream_info->m_pAudioFrame->nb_samples,
			pOutputCodecCtx->sample_fmt, 1);

		dec_channel_layout =
			(pOutputCodecCtx->channel_layout && pOutputCodecCtx->channels == av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout)) ?
			pOutputCodecCtx->channel_layout : av_get_default_channel_layout(pOutputCodecCtx->channels);
		//wanted_nb_samples = SynAudio(strct_stream_info, strct_stream_info->m_pAudioFrame->nb_samples);

		/*if (pOutputCodecCtx->sample_fmt != strct_stream_info->m_audio_src.fmt ||
			dec_channel_layout != strct_stream_info->m_audio_src.channel_layout ||
			pOutputCodecCtx->sample_rate != strct_stream_info->m_audio_src.freq){*/
		swr_free(&strct_stream_info->m_audio_swr_ctx);
		strct_stream_info->m_audio_swr_ctx = swr_alloc_set_opts(NULL,
				strct_stream_info->m_audio_tgt.channel_layout, strct_stream_info->m_audio_tgt.fmt, strct_stream_info->m_audio_tgt.freq,
				dec_channel_layout, pOutputCodecCtx->sample_fmt, pOutputCodecCtx->sample_rate,
				0, NULL);
		if (!strct_stream_info->m_audio_swr_ctx || swr_init(strct_stream_info->m_audio_swr_ctx) < 0){
				TRACE("!pThis->m_pStreamInfstrct_stream_infoo->m_audio_swr_ctx || swr_init(strct_stream_info->m_audio_swr_ctx) < 0");
				break;
			}

			strct_stream_info->m_audio_src.channel_layout = dec_channel_layout;
			strct_stream_info->m_audio_src.channels = pOutputCodecCtx->channels;
			strct_stream_info->m_audio_src.freq = pOutputCodecCtx->sample_rate;
			strct_stream_info->m_audio_src.fmt = pOutputCodecCtx->sample_fmt;
		//}
			if (NULL != strct_stream_info->m_audio_swr_ctx){
			const uint8_t **in = (const uint8_t **)strct_stream_info->m_pAudioFrame->extended_data;
			uint8_t *out[] = { strct_stream_info->m_audio_buf2 };
			int out_count = sizeof(strct_stream_info->m_audio_buf2) / strct_stream_info->m_audio_tgt.channels / av_get_bytes_per_sample(strct_stream_info->m_audio_tgt.fmt);
			int iRet = swr_convert(strct_stream_info->m_audio_swr_ctx, out, out_count, in, strct_stream_info->m_pAudioFrame->nb_samples);
			if (iRet < 0){
				TRACE("swr_convert < 0\n");
				break;
			}
			if (iRet == out_count) {
				TRACE("warning: audio buffer is probably too small\n");
				swr_init(strct_stream_info->m_audio_swr_ctx);
			}
			strct_stream_info->m_audio_buf = strct_stream_info->m_audio_buf2;
			resampled_data_size = iRet * strct_stream_info->m_audio_tgt.channels * av_get_bytes_per_sample(strct_stream_info->m_audio_tgt.fmt);
		}
		else{
			strct_stream_info->m_audio_buf = strct_stream_info->m_pAudioFrame->data[0];
			resampled_data_size = data_size;
		}

		/* if no pts, then compute it */
		pts = strct_stream_info->m_audio_clock;
		//*pts_ptr = pts;
		strct_stream_info->m_audio_clock += (double)data_size /
			(pAudioDec->channels * pAudioDec->sample_rate * av_get_bytes_per_sample(pAudioDec->sample_fmt));
#ifdef DEBUG
		{
			static double last_clock;
			/*printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
				is->audio_clock - last_clock,
				is->audio_clock, pts);*/
			last_clock = strct_stream_info->m_audio_clock;
		}
#endif

		//FIX:FLAC,MP3,AAC Different number of samples
		/*if (wanted_spec.samples != strct_stream_info->m_pAudioFrame->nb_samples){
			SDL_CloseAudio();
			out_nb_samples = strct_stream_info->m_pAudioFrame->nb_samples;
			out_buffer_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels, out_nb_samples, out_sample_fmt, 1);
			wanted_spec.samples = out_nb_samples;
			SDL_OpenAudio(&wanted_spec, NULL);
		}*/

		//设置PCM数据
		TRACE("----out_buffer_size---is [%ld]\n",out_buffer_size);
		audio_chunk = (Uint8 *)out_buffer;
		audio_len = out_buffer_size;
		audio_pos = audio_chunk;

		strct_stream_info->m_aduio_pkt_size = resampled_data_size;//audio_len;//

		av_free_packet(&pkt);

		//写PCM进行test
		if (1){
			FILE *p = NULL;
			fopen_s(&p, "test.pcm", "a+b");
			if (p == NULL){
				continue;
			}
			int tempLenght = 2 * strct_stream_info->m_pAudioFrame->nb_samples;//由于实验中知道这是16位深,所以才这么写
			uint8_t *tmpPtr = strct_stream_info->m_pAudioFrame->data[0];
			if (NULL != p)
			{
				while (tempLenght > 0)
				{
					size_t temp = fwrite(tmpPtr, 1, tempLenght, p);
					tmpPtr += temp;
					tempLenght = tempLenght - temp;
				}
				fclose(p);
			}
		}

		SDL_PauseAudio(0);
		//while (audio_len > 0){
		//	//Wait until finish
		//	SDL_Delay(1);
		//}

		//if (pFmtCtx->streams[iAudioIndex]->codec->sample_fmt != pOutputCodecCtx->sample_fmt
		//	|| pFmtCtx->streams[iAudioIndex]->codec->channels != pOutputCodecCtx->channels
		//	|| pFmtCtx->streams[iAudioIndex]->codec->sample_rate != pOutputCodecCtx->sample_rate){
		//	//TODO如果输入和输出的音频格式不一样 需要重采样,这里是一样的就没做
		//}

		//av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples);
		//av_audio_fifo_write(fifo, (void **)frame->data, frame->nb_samples);

		////循环读取数据,直到buf里数据采样数不够
		//while (av_audio_fifo_size(fifo) >= (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE))
		//{
		//	av_frame_free(&frame);
		//	frame = av_frame_alloc();
		//	frame->nb_samples = pOutputCodecCtx->frame_size>0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE;
		//	frame->channel_layout = pOutputCodecCtx->channel_layout;
		//	frame->format = pOutputCodecCtx->sample_fmt;
		//	frame->sample_rate = pOutputCodecCtx->sample_rate;
		//	av_frame_get_buffer(frame, 0);

		//	av_audio_fifo_read(fifo, (void **)frame->data, (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE));
		//	av_init_packet(&pkt_out);
		//	//frame->pts = pFrame->pts;
		//	int got_picture = -1;
		//	pkt_out.data = NULL;
		//	pkt_out.size = 0;
		//	if (avcodec_encode_audio2(pOutputCodecCtx, &pkt_out, frame, &got_picture) < 0){
		//		printf("can not decoder a frame");
		//	}
		//	av_frame_free(&frame);
		//	if (got_picture)
		//	{
		//		pkt_out.pts = frameIndex * pOutputCodecCtx->frame_size;
		//		pkt_out.dts = frameIndex * pOutputCodecCtx->frame_size;
		//		pkt_out.duration = pOutputCodecCtx->frame_size;

		//		//TODO将编码结果后续做合成处理[pkt_out]
		//		if (pFile != NULL){
		//			/*fwrite((uint8_t *)pDlg->m_streamstate->audio_buf + pDlg->m_streamstate->audio_buf_index, 1, len1, pFile);*/
		//		}
		//		frameIndex++;
		//	}
		//}
	}
	iRet = 1;

END:
	//swr_free(&au_convert_ctx);
	SDL_CloseAudio();
	SDL_Quit();
	av_free(out_buffer);
	avcodec_close(pOutputCodecCtx);

	return iRet;
}
Esempio n. 2
0
static bool reinitialize_coder(struct libavcodec_codec_state *s, struct audio_desc desc)
{
        av_freep(&s->samples);
        pthread_mutex_lock(s->libav_global_lock);
        avcodec_close(s->codec_ctx);
        pthread_mutex_unlock(s->libav_global_lock);

        /*  put sample parameters */
        s->codec_ctx->bit_rate = 64000;
        s->codec_ctx->sample_rate = desc.sample_rate;
        s->change_bps_to = 0;
        switch(desc.bps) {
                case 1:
                        s->codec_ctx->sample_fmt = AV_SAMPLE_FMT_U8;
                        break;
                case 2:
                        s->codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;
                        break;
                case 3:
                        s->change_bps_to = 4;
                case 4:
                        s->codec_ctx->sample_fmt = AV_SAMPLE_FMT_S32;
                        break;
        }

        if(!check_sample_fmt(s->codec, s->codec_ctx->sample_fmt)) {
                s->codec_ctx->sample_fmt = s->codec->sample_fmts[0];
                s->change_bps_to = av_get_bytes_per_sample(s->codec_ctx->sample_fmt);
        }

        s->codec_ctx->channels = 1;
        s->codec_ctx->channel_layout = AV_CH_LAYOUT_MONO;

        pthread_mutex_lock(s->libav_global_lock);
        /* open it */
        if (avcodec_open2(s->codec_ctx, s->codec, NULL) < 0) {
                fprintf(stderr, "Could not open codec\n");
                pthread_mutex_unlock(s->libav_global_lock);
                return false;
        }
        pthread_mutex_unlock(s->libav_global_lock);

        if(s->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) {
                s->codec_ctx->frame_size = 1;
        }

        s->av_frame->nb_samples     = s->codec_ctx->frame_size;
        s->av_frame->format         = s->codec_ctx->sample_fmt;
        s->av_frame->channel_layout = AV_CH_LAYOUT_MONO;

        int channels = 1;
        /* the codec gives us the frame size, in samples,
         * we calculate the size of the samples buffer in bytes */
        int buffer_size = av_samples_get_buffer_size(NULL, channels, s->codec_ctx->frame_size,
                        s->codec_ctx->sample_fmt, 0);

        s->samples = av_malloc(buffer_size);
        if (!s->samples) {
                fprintf(stderr, "could not allocate %d bytes for samples buffer\n",
                                buffer_size);
                return false;
        }
        /* setup the data pointers in the AVFrame */
        int ret = avcodec_fill_audio_frame(s->av_frame, channels, s->codec_ctx->sample_fmt,
                        (const uint8_t*)s->samples, buffer_size, 0);
        if (ret < 0) {
                fprintf(stderr, "could not setup audio frame\n");
                return false;
        }

        s->output_channel.sample_rate = desc.sample_rate;
        s->output_channel.bps = desc.bps;

        s->saved_desc = desc;

        return true;
}
Esempio n. 3
0
int THMovie::decodeAudioFrame(bool fFirst)
{
    int iBytesConsumed = 0;
    int iSampleSize = 0;
    int iOutSamples;
    int iGotFrame = 0;
    bool fNewPacket = false;
    bool fFlushComplete = false;
    double dClockPts;
    int64_t iStreamPts;

    while(!iGotFrame && !m_fAborting)
    {
        if(!m_pAudioPacket || m_pAudioPacket->size == 0)
        {
            if(m_pAudioPacket)
            {
                m_pAudioPacket->data = m_pbAudioPacketData;
                m_pAudioPacket->size = m_iAudioPacketSize;
                av_packet_unref(m_pAudioPacket);
                av_free(m_pAudioPacket);
                m_pAudioPacket = nullptr;
            }
            m_pAudioPacket = m_pAudioQueue->pull(true);
            if(m_fAborting)
            {
                break;
            }

            m_pbAudioPacketData = m_pAudioPacket->data;
            m_iAudioPacketSize = m_pAudioPacket->size;

            if(m_pAudioPacket == nullptr)
            {
                fNewPacket = false;
                return -1;
            }
            fNewPacket = true;

            if(m_pAudioPacket->data == m_flushPacket->data)
            {
                avcodec_flush_buffers(m_pAudioCodecContext);
                fFlushComplete = false;
            }
        }

        if(fFirst)
        {
            iStreamPts = m_pAudioPacket->pts;
            if(iStreamPts != AV_NOPTS_VALUE)
            {
                //There is a time_base in m_pAudioCodecContext too, but that one is wrong.
                dClockPts = iStreamPts * av_q2d(m_pFormatContext->streams[m_iAudioStream]->time_base);
                m_iCurSyncPts = dClockPts;
                m_iCurSyncPtsSystemTime = SDL_GetTicks();
            }
            fFirst = false;
        }

        while(m_pAudioPacket->size > 0 || (!m_pAudioPacket->data && fNewPacket))
        {
            if(!m_audio_frame)
            {
                m_audio_frame = av_frame_alloc();
            }
            else
            {
                av_frame_unref(m_audio_frame);
            }

            if(fFlushComplete)
            {
                break;
            }

            fNewPacket = false;

            iBytesConsumed = avcodec_decode_audio4(m_pAudioCodecContext, m_audio_frame, &iGotFrame, m_pAudioPacket);

            if(iBytesConsumed < 0)
            {
                m_pAudioPacket->size = 0;
                break;
            }
            m_pAudioPacket->data += iBytesConsumed;
            m_pAudioPacket->size -= iBytesConsumed;

            if(!iGotFrame)
            {
                if(m_pAudioPacket->data && (m_pAudioCodecContext->codec->capabilities & CODEC_CAP_DELAY))
                {
                    fFlushComplete = true;
                }
            }
        }
    }

    //over-estimate output samples
    iOutSamples = (int)av_rescale_rnd(m_audio_frame->nb_samples, m_iMixerFrequency, m_pAudioCodecContext->sample_rate, AV_ROUND_UP);
    iSampleSize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * iOutSamples * m_iMixerChannels;

    if(iSampleSize > m_iAudioBufferMaxSize)
    {
        if(m_iAudioBufferMaxSize > 0)
        {
            av_free(m_pbAudioBuffer);
        }
        m_pbAudioBuffer = (uint8_t*)av_malloc(iSampleSize);
        m_iAudioBufferMaxSize = iSampleSize;
    }

#ifdef CORSIX_TH_USE_FFMPEG
    swr_convert(m_pAudioResampleContext, &m_pbAudioBuffer, iOutSamples, (const uint8_t**)&m_audio_frame->data[0], m_audio_frame->nb_samples);
#elif defined(CORSIX_TH_USE_LIBAV)
    avresample_convert(m_pAudioResampleContext, &m_pbAudioBuffer, 0, iOutSamples, (uint8_t**)&m_audio_frame->data[0], 0, m_audio_frame->nb_samples);
#endif
    return iSampleSize;
}
Esempio n. 4
0
/** @internal @This outputs audio buffers
 *
 * @param upipe description structure of the pipe
 * @param frame AVFrame structure
 * @param upump upump structure
 */
static void upipe_avcdec_output_audio(struct upipe *upipe, AVFrame *frame,
                                     struct upump *upump)
{
    struct ubuf *ubuf;
    struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe);
    struct uref *uref = frame->opaque;
    int bufsize = -1, avbufsize;
    size_t size = 0;
    uint8_t *buf;
    AVCodecContext *context = upipe_avcdec->context;

    /* fetch audio sample size (in case it has been reduced) */
    avbufsize = av_samples_get_buffer_size(NULL, context->channels,
                       frame->nb_samples, context->sample_fmt, 1);

    /* if uref has no attached ubuf (ie DR not supported) */
    if (unlikely(!uref->ubuf)) {
        ubuf = ubuf_block_alloc(upipe_avcdec->ubuf_mgr, avbufsize);
        if (unlikely(!ubuf)) {
            upipe_throw_aerror(upipe);
            return;
        }

        ubuf_block_write(ubuf, 0, &bufsize, &buf);
        memcpy(buf, frame->data[0], bufsize);

        uref_attach_ubuf(uref, ubuf);
    }

    /* unmap, reduce block if needed */
    uref_block_unmap(uref, 0);
    uref_block_size(uref, &size);
    if (unlikely(size != avbufsize)) {
        uref_block_resize(uref, 0, avbufsize);
    }

    /* TODO: set attributes/need a real ubuf_audio structure (?) */
    if (!upipe_avcdec->output_flow) {
        #if 0
        struct uref *outflow = uref_sound_flow_alloc_def(upipe_avcdec->uref_mgr,
                    context->channels,
                    av_get_bytes_per_sample(context->sample_fmt));
        #else

        struct uref *outflow = uref_block_flow_alloc_def(upipe_avcdec->uref_mgr,
                                                        "sound.");

        #endif
        uref_sound_flow_set_channels(outflow, context->channels);
        uref_sound_flow_set_sample_size(outflow,
                                 av_get_bytes_per_sample(context->sample_fmt));
        uref_sound_flow_set_rate(outflow, context->sample_rate);

        upipe_avcdec_store_flow_def(upipe, outflow);
    }

    /* samples in uref */
    uref_sound_flow_set_samples(uref, frame->nb_samples);

    /* index rap attribute */
    upipe_avcdec_set_index_rap(upipe, uref);

    upipe_avcdec_output(upipe, uref, upump);
}
Esempio n. 5
0
int
scan_metadata_ffmpeg(char *file, struct media_file_info *mfi)
{
  AVFormatContext *ctx;
  AVDictionary *options;
  const struct metadata_map *extra_md_map;
  struct http_icy_metadata *icy_metadata;
#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
  enum AVCodecID codec_id;
  enum AVCodecID video_codec_id;
  enum AVCodecID audio_codec_id;
#else
  enum CodecID codec_id;
  enum CodecID video_codec_id;
  enum CodecID audio_codec_id;
#endif
  AVStream *video_stream;
  AVStream *audio_stream;
  char *path;
  int mdcount;
  int i;
  int ret;

  ctx = NULL;
  options = NULL;
  path = strdup(file);

#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
# ifndef HAVE_FFMPEG
  // Without this, libav is slow to probe some internet streams
  if (mfi->data_kind == DATA_KIND_HTTP)
    {
      ctx = avformat_alloc_context();
      ctx->probesize = 64000;
    }
# endif

  if (mfi->data_kind == DATA_KIND_HTTP)
    {
      free(path);
      ret = http_stream_setup(&path, file);
      if (ret < 0)
	return -1;

      av_dict_set(&options, "icy", "1", 0);
      mfi->artwork = ARTWORK_HTTP;
    }

  ret = avformat_open_input(&ctx, path, NULL, &options);

  if (options)
    av_dict_free(&options);
#else
  ret = av_open_input_file(&ctx, path, NULL, 0, NULL);
#endif
  if (ret != 0)
    {
      DPRINTF(E_WARN, L_SCAN, "Cannot open media file '%s': %s\n", path, strerror(AVUNERROR(ret)));

      free(path);
      return -1;
    }

  free(path);

#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
  ret = avformat_find_stream_info(ctx, NULL);
#else
  ret = av_find_stream_info(ctx);
#endif
  if (ret < 0)
    {
      DPRINTF(E_WARN, L_SCAN, "Cannot get stream info: %s\n", strerror(AVUNERROR(ret)));

#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21)
      avformat_close_input(&ctx);
#else
      av_close_input_file(ctx);
#endif
      return -1;
    }

#if 0
  /* Dump input format as determined by ffmpeg */
  av_dump_format(ctx, 0, file, 0);
#endif

  DPRINTF(E_DBG, L_SCAN, "File has %d streams\n", ctx->nb_streams);

  /* Extract codec IDs, check for video */
#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
  video_codec_id = AV_CODEC_ID_NONE;
  video_stream = NULL;

  audio_codec_id = AV_CODEC_ID_NONE;
  audio_stream = NULL;
#else
  video_codec_id = CODEC_ID_NONE;
  video_stream = NULL;

  audio_codec_id = CODEC_ID_NONE;
  audio_stream = NULL;
#endif

  for (i = 0; i < ctx->nb_streams; i++)
    {
      switch (ctx->streams[i]->codec->codec_type)
	{
#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64)
	  case AVMEDIA_TYPE_VIDEO:
#else
	  case CODEC_TYPE_VIDEO:
#endif
#if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6)
	    if (ctx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
	      {
		DPRINTF(E_DBG, L_SCAN, "Found embedded artwork (stream %d)\n", i);
		mfi->artwork = ARTWORK_EMBEDDED;

		break;
	      }
#endif
	    // We treat these as audio no matter what
	    if (mfi->compilation || (mfi->media_kind & (MEDIA_KIND_PODCAST | MEDIA_KIND_AUDIOBOOK)))
	      break;

	    if (!video_stream)
	      {
		DPRINTF(E_DBG, L_SCAN, "File has video (stream %d)\n", i);

		mfi->has_video = 1;
		video_stream = ctx->streams[i];
		video_codec_id = video_stream->codec->codec_id;
	      }
	    break;

#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64)
	  case AVMEDIA_TYPE_AUDIO:
#else
	  case CODEC_TYPE_AUDIO:
#endif
	    if (!audio_stream)
	      {
		audio_stream = ctx->streams[i];
		audio_codec_id = audio_stream->codec->codec_id;
	      } 
	    break;

	  default:
	    break;
	}
    }

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
  if (audio_codec_id == AV_CODEC_ID_NONE)
#else
  if (audio_codec_id == CODEC_ID_NONE)
#endif
    {
      DPRINTF(E_DBG, L_SCAN, "File has no audio streams, discarding\n");

#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21)
      avformat_close_input(&ctx);
#else
      av_close_input_file(ctx);
#endif
      return -1;
    }

  /* Common media information */
  if (ctx->duration > 0)
    mfi->song_length = ctx->duration / (AV_TIME_BASE / 1000); /* ms */

  if (ctx->bit_rate > 0)
    mfi->bitrate = ctx->bit_rate / 1000;
  else if (ctx->duration > AV_TIME_BASE) /* guesstimate */
    mfi->bitrate = ((mfi->file_size * 8) / (ctx->duration / AV_TIME_BASE)) / 1000;

  DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate);

  /* Try to extract ICY metadata if http stream */
  if (mfi->data_kind == DATA_KIND_HTTP)
    {
      icy_metadata = http_icy_metadata_get(ctx, 0);
      if (icy_metadata && icy_metadata->name)
	{
	  DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, name is '%s'\n", icy_metadata->name);

	  if (mfi->title)
	    free(mfi->title);
	  if (mfi->artist)
	    free(mfi->artist);
	  if (mfi->album_artist)
	    free(mfi->album_artist);

	  mfi->title = strdup(icy_metadata->name);
	  mfi->artist = strdup(icy_metadata->name);
	  mfi->album_artist = strdup(icy_metadata->name);
	}
      if (icy_metadata && icy_metadata->description)
	{
	  DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, description is '%s'\n", icy_metadata->description);

	  if (mfi->album)
	    free(mfi->album);

	  mfi->album = strdup(icy_metadata->description);
	}
      if (icy_metadata && icy_metadata->genre)
	{
	  DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, genre is '%s'\n", icy_metadata->genre);

	  if (mfi->genre)
	    free(mfi->genre);

	  mfi->genre = strdup(icy_metadata->genre);
	}
      if (icy_metadata)
	http_icy_metadata_free(icy_metadata, 0);
    }

  /* Get some more information on the audio stream */
  if (audio_stream)
    {
      if (audio_stream->codec->sample_rate != 0)
	mfi->samplerate = audio_stream->codec->sample_rate;

      /* Try sample format first */
#if LIBAVUTIL_VERSION_MAJOR >= 52 || (LIBAVUTIL_VERSION_MAJOR == 51 && LIBAVUTIL_VERSION_MINOR >= 4)
      mfi->bits_per_sample = 8 * av_get_bytes_per_sample(audio_stream->codec->sample_fmt);
#elif LIBAVCODEC_VERSION_MAJOR >= 53
      mfi->bits_per_sample = av_get_bits_per_sample_fmt(audio_stream->codec->sample_fmt);
#else
      mfi->bits_per_sample = av_get_bits_per_sample_format(audio_stream->codec->sample_fmt);
#endif
      if (mfi->bits_per_sample == 0)
	{
	  /* Try codec */
	  mfi->bits_per_sample = av_get_bits_per_sample(audio_codec_id);
	}

      DPRINTF(E_DBG, L_SCAN, "samplerate %d, bps %d\n", mfi->samplerate, mfi->bits_per_sample);
    }

  /* Check codec */
  extra_md_map = NULL;
  codec_id = (mfi->has_video) ? video_codec_id : audio_codec_id;
  switch (codec_id)
    {
#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_AAC:
#else
      case CODEC_ID_AAC:
#endif
	DPRINTF(E_DBG, L_SCAN, "AAC\n");
	mfi->type = strdup("m4a");
	mfi->codectype = strdup("mp4a");
	mfi->description = strdup("AAC audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_ALAC:
#else
      case CODEC_ID_ALAC:
#endif
	DPRINTF(E_DBG, L_SCAN, "ALAC\n");
	mfi->type = strdup("m4a");
	mfi->codectype = strdup("alac");
	mfi->description = strdup("Apple Lossless audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_FLAC:
#else
      case CODEC_ID_FLAC:
#endif
	DPRINTF(E_DBG, L_SCAN, "FLAC\n");
	mfi->type = strdup("flac");
	mfi->codectype = strdup("flac");
	mfi->description = strdup("FLAC audio file");

	extra_md_map = md_map_vorbis;
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_MUSEPACK7:
      case AV_CODEC_ID_MUSEPACK8:
#else
      case CODEC_ID_MUSEPACK7:
      case CODEC_ID_MUSEPACK8:
#endif
	DPRINTF(E_DBG, L_SCAN, "Musepack\n");
	mfi->type = strdup("mpc");
	mfi->codectype = strdup("mpc");
	mfi->description = strdup("Musepack audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_MPEG4: /* Video */
      case AV_CODEC_ID_H264:
#else
      case CODEC_ID_MPEG4: /* Video */
      case CODEC_ID_H264:
#endif
	DPRINTF(E_DBG, L_SCAN, "MPEG4 video\n");
	mfi->type = strdup("m4v");
	mfi->codectype = strdup("mp4v");
	mfi->description = strdup("MPEG-4 video file");

	extra_md_map = md_map_tv;
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_MP3:
#else
      case CODEC_ID_MP3:
#endif
	DPRINTF(E_DBG, L_SCAN, "MP3\n");
	mfi->type = strdup("mp3");
	mfi->codectype = strdup("mpeg");
	mfi->description = strdup("MPEG audio file");

	extra_md_map = md_map_id3;
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_VORBIS:
#else
      case CODEC_ID_VORBIS:
#endif
	DPRINTF(E_DBG, L_SCAN, "VORBIS\n");
	mfi->type = strdup("ogg");
	mfi->codectype = strdup("ogg");
	mfi->description = strdup("Ogg Vorbis audio file");

	extra_md_map = md_map_vorbis;
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_WMAV1:
      case AV_CODEC_ID_WMAV2:
      case AV_CODEC_ID_WMAVOICE:
#else
      case CODEC_ID_WMAV1:
      case CODEC_ID_WMAV2:
      case CODEC_ID_WMAVOICE:
#endif
	DPRINTF(E_DBG, L_SCAN, "WMA Voice\n");
	mfi->type = strdup("wma");
	mfi->codectype = strdup("wmav");
	mfi->description = strdup("WMA audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_WMAPRO:
#else
      case CODEC_ID_WMAPRO:
#endif
	DPRINTF(E_DBG, L_SCAN, "WMA Pro\n");
	mfi->type = strdup("wmap");
	mfi->codectype = strdup("wma");
	mfi->description = strdup("WMA audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_WMALOSSLESS:
#else
      case CODEC_ID_WMALOSSLESS:
#endif
	DPRINTF(E_DBG, L_SCAN, "WMA Lossless\n");
	mfi->type = strdup("wma");
	mfi->codectype = strdup("wmal");
	mfi->description = strdup("WMA audio file");
	break;

#if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35)
      case AV_CODEC_ID_PCM_S16LE ... AV_CODEC_ID_PCM_F64LE:
#else
      case CODEC_ID_PCM_S16LE ... CODEC_ID_PCM_F64LE:
#endif
	if (strcmp(ctx->iformat->name, "aiff") == 0)
	  {
	    DPRINTF(E_DBG, L_SCAN, "AIFF\n");
	    mfi->type = strdup("aif");
	    mfi->codectype = strdup("aif");
	    mfi->description = strdup("AIFF audio file");
	    break;
	  }
	else if (strcmp(ctx->iformat->name, "wav") == 0)
	  {
	    DPRINTF(E_DBG, L_SCAN, "WAV\n");
	    mfi->type = strdup("wav");
	    mfi->codectype = strdup("wav");
	    mfi->description = strdup("WAV audio file");
	    break;
	  }
	/* WARNING: will fallthrough to default case, don't move */
	/* FALLTHROUGH */

      default:
	DPRINTF(E_DBG, L_SCAN, "Unknown codec 0x%x (video: %s), format %s (%s)\n",
		codec_id, (mfi->has_video) ? "yes" : "no", ctx->iformat->name, ctx->iformat->long_name);
	mfi->type = strdup("unkn");
	mfi->codectype = strdup("unkn");
	if (mfi->has_video)
	  {
	    mfi->description = strdup("Unknown video file format");
	    extra_md_map = md_map_tv;
	  }
	else
	  mfi->description = strdup("Unknown audio file format");
	break;
    }

  mdcount = 0;

  if ((!ctx->metadata) && (!audio_stream->metadata)
      && (video_stream && !video_stream->metadata))
    {
      DPRINTF(E_WARN, L_SCAN, "ffmpeg reports no metadata\n");

      goto skip_extract;
    }

  if (extra_md_map)
    {
      ret = extract_metadata(mfi, ctx, audio_stream, video_stream, extra_md_map);
      mdcount += ret;

      DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with extra md_map\n", ret);
    }

  ret = extract_metadata(mfi, ctx, audio_stream, video_stream, md_map_generic);
  mdcount += ret;

  DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with generic md_map, %d tags total\n", ret, mdcount);

  /* fix up TV metadata */
  if (mfi->media_kind == 10)
    {
      /* I have no idea why this is, but iTunes reports a media kind of 64 for stik==10 (?!) */
      mfi->media_kind = MEDIA_KIND_TVSHOW;
    }
  /* Unspecified video files are "Movies", media_kind 2 */
  else if (mfi->has_video == 1)
    {
      mfi->media_kind = MEDIA_KIND_MOVIE;
    }

 skip_extract:
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21)
  avformat_close_input(&ctx);
#else
  av_close_input_file(ctx);
#endif

  if (mdcount == 0)
    DPRINTF(E_WARN, L_SCAN, "ffmpeg/libav could not extract any metadata\n");

  /* Just in case there's no title set ... */
  if (mfi->title == NULL)
    mfi->title = strdup(mfi->fname);

  /* All done */

  return 0;
}
Esempio n. 6
0
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
    int out_i, in_i, i, j;
    int len1 = 0;
    int off = 0;

    if(s->mix_any_f) {
        s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
        return 0;
    }

    if(s->mix_2_1_simd || s->mix_1_1_simd){
        len1= len&~15;
        off = len1 * out->bps;
    }

    av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
    av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));

    for(out_i=0; out_i<out->ch_count; out_i++){
        switch(s->matrix_ch[out_i][0]){
        case 0:
            if(mustcopy)
                memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
            break;
        case 1:
            in_i= s->matrix_ch[out_i][1];
            if(s->matrix[out_i][in_i]!=1.0){
                if(s->mix_1_1_simd && len1)
                    s->mix_1_1_simd(out->ch[out_i]    , in->ch[in_i]    , s->native_simd_matrix, in->ch_count*out_i + in_i, len1);
                if(len != len1)
                    s->mix_1_1_f   (out->ch[out_i]+off, in->ch[in_i]+off, s->native_matrix, in->ch_count*out_i + in_i, len-len1);
            }else if(mustcopy){
                memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
            }else{
                out->ch[out_i]= in->ch[in_i];
            }
            break;
        case 2: {
            int in_i1 = s->matrix_ch[out_i][1];
            int in_i2 = s->matrix_ch[out_i][2];
            if(s->mix_2_1_simd && len1)
                s->mix_2_1_simd(out->ch[out_i]    , in->ch[in_i1]    , in->ch[in_i2]    , s->native_simd_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
            else
                s->mix_2_1_f   (out->ch[out_i]    , in->ch[in_i1]    , in->ch[in_i2]    , s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
            if(len != len1)
                s->mix_2_1_f   (out->ch[out_i]+off, in->ch[in_i1]+off, in->ch[in_i2]+off, s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len-len1);
            break;}
        default:
            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
                for(i=0; i<len; i++){
                    float v=0;
                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
                        in_i= s->matrix_ch[out_i][1+j];
                        v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i];
                    }
                    ((float*)out->ch[out_i])[i]= v;
                }
            }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
                for(i=0; i<len; i++){
                    double v=0;
                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
                        in_i= s->matrix_ch[out_i][1+j];
                        v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
                    }
                    ((double*)out->ch[out_i])[i]= v;
                }
            }else{
                for(i=0; i<len; i++){
                    int v=0;
                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
                        in_i= s->matrix_ch[out_i][1+j];
                        v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
                    }
                    ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
                }
            }
        }
    }
    return 0;
}
int audio_decode_frame(VideoState *is, double *pts_ptr) {
  int len1, data_size = 0, n;
  AVPacket *pkt = &is->audio_pkt;
  double pts;
    
    uint8_t *out[] = {is->audio_buf};
    int64_t wanted_channel_layout = 0;
    wanted_channel_layout = is->audio_st->codec->channel_layout;
    SwrContext* t_audio_conv = swr_alloc_set_opts(NULL,
                                                  wanted_channel_layout,AV_SAMPLE_FMT_S16,is->audio_st->codec->sample_rate,
                                                  wanted_channel_layout,is->audio_st->codec->sample_fmt, is->audio_st->codec->sample_rate,
                                                  0,NULL);
    swr_init(t_audio_conv);
    
    for(;;) {
        while(is->audio_pkt_size > 0)
        {
            int got_frame = 0;
            int t_audio_size= 0;
            len1 = avcodec_decode_audio4(is->audio_st->codec, &is->audio_frame, &got_frame, pkt);
            if(len1 < 0) {
                /* if error, skip frame */
                is->audio_pkt_size = 0;
                break;
            }
            if (got_frame)
            {
                
                int size1 = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
                int len = swr_convert(t_audio_conv,
                                      out, (MAX_AUDIO_FRAME_SIZE * 3) / 2/is->audio_st->codec->channels/size1,
                                      (const uint8_t **)is->audio_frame.extended_data, is->audio_frame.nb_samples);
                
                t_audio_size = len * is->audio_st->codec->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
                
                
                //av_packet_unref(pkt);
                swr_free(&t_audio_conv);
                //return len;
                
            }
            is->audio_pkt_data += len1;
            is->audio_pkt_size -= len1;
            //if(data_size <= 0) {
            if(t_audio_size <= 0) {
                /* No data yet, get more frames */
                continue;
            }
            pts = is->audio_clock;
            *pts_ptr = pts;
            n = 2*is->audio_st->codec->channels;
            is->audio_clock += (double)data_size /
            (double)(n * is->audio_st->codec->sample_rate);
            
            /* We have data, return it and come back for more later */
            //return data_size;
            return t_audio_size;
        }
        if(pkt->data)
            av_free_packet(pkt);
        
        if(is->quit) {
            return -1;
        }
        /* next packet */
        if(packet_queue_get(&is->audioq, pkt, 1) < 0) {
            return -1;
        }
        is->audio_pkt_data = pkt->data;
        is->audio_pkt_size = pkt->size;
        
        /* if update, update the audio clock w/pts */
        if(pkt->pts != AV_NOPTS_VALUE) {
            is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
        }
    }
    
//    
//  for(;;) {
//    while(is->audio_pkt_size > 0) {
//      int got_frame;
//      len1 = avcodec_decode_audio4(is->audio_st->codec, &is->audio_frame, &got_frame, pkt);
//      if(len1 < 0) {
//	/* if error, skip frame */
//	is->audio_pkt_size = 0;
//	break;
//      }
//      if (got_frame)
//      {
//          data_size = 
//            av_samples_get_buffer_size
//            (
//                NULL, 
//                is->audio_st->codec->channels,
//                is->audio_frame.nb_samples,
//                is->audio_st->codec->sample_fmt,
//                1
//            );
//          memcpy(is->audio_buf, is->audio_frame.data[0], data_size);
//      }
//      is->audio_pkt_data += len1;
//      is->audio_pkt_size -= len1;
//      if(data_size <= 0) {
//	/* No data yet, get more frames */
//	continue;
//      }
//      pts = is->audio_clock;
//      *pts_ptr = pts;
//      n = 2 * is->audio_st->codec->channels;
//      is->audio_clock += (double)data_size /
//	(double)(n * is->audio_st->codec->sample_rate);
//
//      /* We have data, return it and come back for more later */
//      return data_size;
//    }
//    if(pkt->data)
//      av_free_packet(pkt);
//
//    if(is->quit) {
//      return -1;
//    }
//    /* next packet */
//    if(packet_queue_get(&is->audioq, pkt, 1) < 0) {
//      return -1;
//    }
//    is->audio_pkt_data = pkt->data;
//    is->audio_pkt_size = pkt->size;
//    /* if update, update the audio clock w/pts */
//    if(pkt->pts != AV_NOPTS_VALUE) {
//      is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
//    }
//
//  }
    return 0;
}
Esempio n. 8
0
int AudioLoader::decode_audio_frame(AVCodecContext* audioCtx,
                                    float* output,
                                    int* outputSize,
                                    AVPacket* packet) {

    // _dataSize  input = number of bytes available for write in buff
    //           output = number of bytes actually written (actual: FLT data)
    //E_DEBUG(EAlgorithm, "decode_audio_frame, available bytes in buffer = " << _dataSize);
    int gotFrame = 0;
    av_frame_unref(_decodedFrame); //avcodec_get_frame_defaults(_decodedFrame);

    int len = avcodec_decode_audio4(audioCtx, _decodedFrame, &gotFrame, packet);

    if (len < 0) return len; // error handling should be done outside

    if (gotFrame) {
        int inputSamples = _decodedFrame->nb_samples;
        int inputPlaneSize = av_samples_get_buffer_size(NULL, _nChannels, inputSamples,
                                                        audioCtx->sample_fmt, 1);
        int outputPlaneSize = av_samples_get_buffer_size(NULL, _nChannels, inputSamples,
                                                        AV_SAMPLE_FMT_FLT, 1);
        // the size of the output buffer in samples
        int outputBufferSamples = *outputSize / 
                (av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT) * _nChannels);

        if (outputBufferSamples < inputSamples) { 
            // this should never happen, throw exception here
            throw EssentiaException("AudioLoader: Insufficient buffer size for format conversion");
        }

        if (audioCtx->sample_fmt == AV_SAMPLE_FMT_FLT) {
            // TODO: no need in this check? Not many of common formats support FLT
            // no conversion needed, direct copy from our frame to output buffer
            memcpy(output, _decodedFrame->data[0], inputPlaneSize);
        }
        else {
          int samplesWrittern = avresample_convert(_convertCtxAv, 
                                          (uint8_t**) &output, 
                                          outputPlaneSize,
                                          outputBufferSamples, 
                                          (uint8_t**)_decodedFrame->data,               
                                          inputPlaneSize, 
                                          inputSamples);

          if (samplesWrittern < inputSamples) {
              // TODO: there may be data remaining in the internal FIFO buffer
              // to get this data: call avresample_convert() with NULL input 
              // Test if this happens in practice
              ostringstream msg;
              msg << "AudioLoader: Incomplete format conversion (some samples missing)"
                  << " from " << av_get_sample_fmt_name(_audioCtx->sample_fmt)
                  << " to "   << av_get_sample_fmt_name(AV_SAMPLE_FMT_FLT);
              throw EssentiaException(msg);
          }
        }
        *outputSize = outputPlaneSize;
    }
    else {
      E_DEBUG(EAlgorithm, "AudioLoader: tried to decode packet but didn't get any frame...");
      *outputSize = 0;
    }

    return len;
}
Esempio n. 9
0
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
    AVFilterContext  *ctx = inlink->dst;
    ASyncContext       *s = ctx->priv;
    AVFilterLink *outlink = ctx->outputs[0];
    int nb_channels = av_get_channel_layout_nb_channels(buf->channel_layout);
    int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
                  av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
    int out_size, ret;
    int64_t delta;
    int64_t new_pts;

    /* buffer data until we get the next timestamp */
    if (s->pts == AV_NOPTS_VALUE || pts == AV_NOPTS_VALUE) {
        if (pts != AV_NOPTS_VALUE) {
            s->pts = pts - get_delay(s);
        }
        return write_to_fifo(s, buf);
    }

    if (s->first_pts != AV_NOPTS_VALUE) {
        handle_trimming(ctx);
        if (!avresample_available(s->avr))
            return write_to_fifo(s, buf);
    }

    /* when we have two timestamps, compute how many samples would we have
     * to add/remove to get proper sync between data and timestamps */
    delta    = pts - s->pts - get_delay(s);
    out_size = avresample_available(s->avr);

    if (llabs(delta) > s->min_delta ||
        (s->first_frame && delta && s->first_pts != AV_NOPTS_VALUE)) {
        av_log(ctx, AV_LOG_VERBOSE, "Discontinuity - %"PRId64" samples.\n", delta);
        out_size = av_clipl_int32((int64_t)out_size + delta);
    } else {
        if (s->resample) {
            // adjust the compensation if delta is non-zero
            int delay = get_delay(s);
            int comp = s->comp + av_clip(delta * inlink->sample_rate / delay,
                                         -s->max_comp, s->max_comp);
            if (comp != s->comp) {
                av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
                if (avresample_set_compensation(s->avr, comp, inlink->sample_rate) == 0) {
                    s->comp = comp;
                }
            }
        }
        // adjust PTS to avoid monotonicity errors with input PTS jitter
        pts -= delta;
        delta = 0;
    }

    if (out_size > 0) {
        AVFrame *buf_out = ff_get_audio_buffer(outlink, out_size);
        if (!buf_out) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }

        if (s->first_frame && delta > 0) {
            int planar = av_sample_fmt_is_planar(buf_out->format);
            int planes = planar ?  nb_channels : 1;
            int block_size = av_get_bytes_per_sample(buf_out->format) *
                             (planar ? 1 : nb_channels);

            int ch;

            av_samples_set_silence(buf_out->extended_data, 0, delta,
                                   nb_channels, buf->format);

            for (ch = 0; ch < planes; ch++)
                buf_out->extended_data[ch] += delta * block_size;

            avresample_read(s->avr, buf_out->extended_data, out_size);

            for (ch = 0; ch < planes; ch++)
                buf_out->extended_data[ch] -= delta * block_size;
        } else {
            avresample_read(s->avr, buf_out->extended_data, out_size);

            if (delta > 0) {
                av_samples_set_silence(buf_out->extended_data, out_size - delta,
                                       delta, nb_channels, buf->format);
            }
        }
        buf_out->pts = s->pts;
        ret = ff_filter_frame(outlink, buf_out);
        if (ret < 0)
            goto fail;
        s->got_output = 1;
    } else if (avresample_available(s->avr)) {
        av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
               "whole buffer.\n");
    }

    /* drain any remaining buffered data */
    avresample_read(s->avr, NULL, avresample_available(s->avr));

    new_pts = pts - avresample_get_delay(s->avr);
    /* check for s->pts monotonicity */
    if (new_pts > s->pts) {
        s->pts = new_pts;
        ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
                                 buf->linesize[0], buf->nb_samples);
    } else {
        av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
               "whole buffer.\n");
        ret = 0;
    }

    s->first_frame = 0;
fail:
    av_frame_free(&buf);

    return ret;
}
Esempio n. 10
0
 size_t getSampleOffset()
 {
     ssize_t clock_delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) /
                           av_get_bytes_per_sample(mOutputSampleFormat);
     return (size_t)(mAudioClock*mAudioContext->sample_rate) - clock_delay;
 }
Esempio n. 11
0
ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta){
    double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
    int phase_count= 1<<phase_shift;

    if (!c || c->phase_shift != phase_shift || c->linear!=linear || c->factor != factor
           || c->filter_length != FFMAX((int)ceil(filter_size/factor), 1) || c->format != format
           || c->filter_type != filter_type || c->kaiser_beta != kaiser_beta) {
        c = av_mallocz(sizeof(*c));
        if (!c)
            return NULL;

        c->format= format;

        c->felem_size= av_get_bytes_per_sample(c->format);

        switch(c->format){
        case AV_SAMPLE_FMT_S16P:
            c->filter_shift = 15;
            break;
        case AV_SAMPLE_FMT_S32P:
            c->filter_shift = 30;
            break;
        case AV_SAMPLE_FMT_FLTP:
        case AV_SAMPLE_FMT_DBLP:
            c->filter_shift = 0;
            break;
        default:
            av_log(NULL, AV_LOG_ERROR, "Unsupported sample format\n");
            return NULL;
        }

        c->phase_shift   = phase_shift;
        c->phase_mask    = phase_count - 1;
        c->linear        = linear;
        c->factor        = factor;
        c->filter_length = FFMAX((int)ceil(filter_size/factor), 1);
        c->filter_alloc  = FFALIGN(c->filter_length, 8);
        c->filter_bank   = av_mallocz(c->filter_alloc*(phase_count+1)*c->felem_size);
        c->filter_type   = filter_type;
        c->kaiser_beta   = kaiser_beta;
        if (!c->filter_bank)
            goto error;
        if (build_filter(c, (void*)c->filter_bank, factor, c->filter_length, c->filter_alloc, phase_count, 1<<c->filter_shift, filter_type, kaiser_beta))
            goto error;
        memcpy(c->filter_bank + (c->filter_alloc*phase_count+1)*c->felem_size, c->filter_bank, (c->filter_alloc-1)*c->felem_size);
        memcpy(c->filter_bank + (c->filter_alloc*phase_count  )*c->felem_size, c->filter_bank + (c->filter_alloc - 1)*c->felem_size, c->felem_size);
    }

    c->compensation_distance= 0;
    if(!av_reduce(&c->src_incr, &c->dst_incr, out_rate, in_rate * (int64_t)phase_count, INT32_MAX/2))
        goto error;
    c->ideal_dst_incr= c->dst_incr;

    c->index= -phase_count*((c->filter_length-1)/2);
    c->frac= 0;

    return c;
error:
    av_free(c->filter_bank);
    av_free(c);
    return NULL;
}
Esempio n. 12
0
int decode_audio_file(ChromaprintContext *chromaprint_ctx, int16_t *buffer1, int16_t *buffer2, const char *file_name, int max_length, int *duration)
{
	int i, ok = 0, remaining, length, consumed, buffer_size, codec_ctx_opened = 0;
	AVFormatContext *format_ctx = NULL;
	AVCodecContext *codec_ctx = NULL;
	AVCodec *codec = NULL;
	AVStream *stream = NULL;
	AVPacket packet, packet_temp;
#ifdef HAVE_AV_AUDIO_CONVERT
	AVAudioConvert *convert_ctx = NULL;
#endif
	int16_t *buffer;

	if (!strcmp(file_name, "-")) {
		file_name = "pipe:0";
	}

#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 2, 0)
	if (av_open_input_file(&format_ctx, file_name, NULL, 0, NULL) != 0) {
#else
	if (avformat_open_input(&format_ctx, file_name, NULL, NULL) != 0) {
#endif
		fprintf(stderr, "ERROR: couldn't open the file\n");
		goto done;
	}

	if (av_find_stream_info(format_ctx) < 0) {
		fprintf(stderr, "ERROR: couldn't find stream information in the file\n");
		goto done;
	}

	for (i = 0; i < format_ctx->nb_streams; i++) {
		codec_ctx = format_ctx->streams[i]->codec;
		if (codec_ctx && codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
			stream = format_ctx->streams[i];
			break;
		}
	}
	if (!stream) {
		fprintf(stderr, "ERROR: couldn't find any audio stream in the file\n");
		goto done;
	}

	codec = avcodec_find_decoder(codec_ctx->codec_id);
	if (!codec) {
		fprintf(stderr, "ERROR: unknown codec\n");
		goto done;
	}

	if (avcodec_open(codec_ctx, codec) < 0) {
		fprintf(stderr, "ERROR: couldn't open the codec\n");
		goto done;
	}
	codec_ctx_opened = 1;

	if (codec_ctx->channels <= 0) {
		fprintf(stderr, "ERROR: no channels found in the audio stream\n");
		goto done;
	}

	if (codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16) {
#ifdef HAVE_AV_AUDIO_CONVERT
		convert_ctx = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, codec_ctx->channels,
		                                     codec_ctx->sample_fmt, codec_ctx->channels, NULL, 0);
		if (!convert_ctx) {
			fprintf(stderr, "ERROR: couldn't create sample format converter\n");
			goto done;
		}
#else
		fprintf(stderr, "ERROR: unsupported sample format\n");
		goto done;
#endif
	}

	*duration = stream->time_base.num * stream->duration / stream->time_base.den;

	av_init_packet(&packet);
	av_init_packet(&packet_temp);

	remaining = max_length * codec_ctx->channels * codec_ctx->sample_rate;
	chromaprint_start(chromaprint_ctx, codec_ctx->sample_rate, codec_ctx->channels);

	while (1) {
		if (av_read_frame(format_ctx, &packet) < 0) {
			break;
		}

		packet_temp.data = packet.data;
		packet_temp.size = packet.size;

		while (packet_temp.size > 0) {
			buffer_size = BUFFER_SIZE;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 23, 0)
			consumed = avcodec_decode_audio2(codec_ctx,
				buffer1, &buffer_size, packet_temp.data, packet_temp.size);
#else
			consumed = avcodec_decode_audio3(codec_ctx,
				buffer1, &buffer_size, &packet_temp);
#endif

			if (consumed < 0) {
				break;
			}

			packet_temp.data += consumed;
			packet_temp.size -= consumed;

			if (buffer_size <= 0) {
				if (buffer_size < 0) {
					fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too small\n");
				}
				continue;
			}
			if (buffer_size > BUFFER_SIZE) {
				fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too large\n");
				continue;
			}

#ifdef HAVE_AV_AUDIO_CONVERT
			if (convert_ctx) {
				const void *ibuf[6] = { buffer1 };
				void *obuf[6] = { buffer2 };
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 8, 0)
				int istride[6] = { av_get_bits_per_sample_format(codec_ctx->sample_fmt) / 8 };
#else
				int istride[6] = { av_get_bytes_per_sample(codec_ctx->sample_fmt) };
#endif
				int ostride[6] = { 2 };
				int len = buffer_size / istride[0];
				if (av_audio_convert(convert_ctx, obuf, ostride, ibuf, istride, len) < 0) {
					break;
				}
				buffer = buffer2;
				buffer_size = len * ostride[0];
			}
			else {
				buffer = buffer1;
			}
#else
			buffer = buffer1;
#endif

			length = MIN(remaining, buffer_size / 2);
			if (!chromaprint_feed(chromaprint_ctx, buffer, length)) {
				fprintf(stderr, "ERROR: fingerprint calculation failed\n");
				goto done;
			}

			if (max_length) {
				remaining -= length;
				if (remaining <= 0) {
					goto finish;
				}
			}
		}

		if (packet.data) {
			av_free_packet(&packet);
		}
	}

finish:
	if (!chromaprint_finish(chromaprint_ctx)) {
		fprintf(stderr, "ERROR: fingerprint calculation failed\n");
		goto done;
	}

	ok = 1;

done:
	if (codec_ctx_opened) {
		avcodec_close(codec_ctx);
	}
	if (format_ctx) {
		av_close_input_file(format_ctx);
	}
#ifdef HAVE_AV_AUDIO_CONVERT
	if (convert_ctx) {
		av_audio_convert_free(convert_ctx);
	}
#endif
	return ok;
}

int fpcalc_main(int argc, char **argv)
{
	int i, j, max_length = 120, num_file_names = 0, raw = 0, raw_fingerprint_size, duration;
	int16_t *buffer1, *buffer2;
	int32_t *raw_fingerprint;
	char *file_name, *fingerprint, **file_names;
	ChromaprintContext *chromaprint_ctx;
	int algo = CHROMAPRINT_ALGORITHM_DEFAULT;

	file_names = malloc(argc * sizeof(char *));
	for (i = 1; i < argc; i++) {
		char *arg = argv[i];
		if (!strcmp(arg, "-length") && i + 1 < argc) {
			max_length = atoi(argv[++i]);
		}
		else if (!strcmp(arg, "-version") || !strcmp(arg, "-v")) {
			printf("fpcalc version %s\n", chromaprint_get_version());
			return 0;
		}
		else if (!strcmp(arg, "-raw")) {
			raw = 1;
		}
		else if (!strcmp(arg, "-algo") && i + 1 < argc) {
			const char *v = argv[++i];
			if (!strcmp(v, "test1")) { algo = CHROMAPRINT_ALGORITHM_TEST1; }
			else if (!strcmp(v, "test2")) { algo = CHROMAPRINT_ALGORITHM_TEST2; }
			else if (!strcmp(v, "test3")) { algo = CHROMAPRINT_ALGORITHM_TEST3; }
			else if (!strcmp(v, "test4")) { algo = CHROMAPRINT_ALGORITHM_TEST4; }
			else {
				fprintf(stderr, "WARNING: unknown algorithm, using the default\n");
			}
		}
		else if (!strcmp(arg, "-set") && i + 1 < argc) {
			i += 1;
		}
		else {
			file_names[num_file_names++] = argv[i];
		}
	}

	if (!num_file_names) {
		printf("usage: %s [OPTIONS] FILE...\n\n", argv[0]);
		printf("Options:\n");
		printf("  -version      print version information\n");
		printf("  -length SECS  length of the audio data used for fingerprint calculation (default 120)\n");
		printf("  -raw          output the raw uncompressed fingerprint\n");
		printf("  -algo NAME    version of the fingerprint algorithm\n");
		return 2;
	}

	av_register_all();
	av_log_set_level(AV_LOG_ERROR);

	buffer1 = av_malloc(BUFFER_SIZE + 16);
	buffer2 = av_malloc(BUFFER_SIZE + 16);
	chromaprint_ctx = chromaprint_new(algo);

	for (i = 1; i < argc; i++) {
		char *arg = argv[i];
		if (!strcmp(arg, "-set") && i + 1 < argc) {
			char *name = argv[++i];
			char *value = strchr(name, '=');
			if (value) {
				*value++ = '\0';
				chromaprint_set_option(chromaprint_ctx, name, atoi(value));
			}
		}
	}

	for (i = 0; i < num_file_names; i++) {
		file_name = file_names[i];
		if (!decode_audio_file(chromaprint_ctx, buffer1, buffer2, file_name, max_length, &duration)) {
			fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
			continue;
		}
		if (i > 0) {
			printf("\n");
		}
		printf("FILE=%s\n", file_name);
		printf("DURATION=%d\n", duration);
		if (raw) {
			if (!chromaprint_get_raw_fingerprint(chromaprint_ctx, (void **)&raw_fingerprint, &raw_fingerprint_size)) {
				fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
				continue;
			}
			printf("FINGERPRINT=");
			for (j = 0; j < raw_fingerprint_size; j++) {
				printf("%d%s", raw_fingerprint[j], j + 1 < raw_fingerprint_size ? "," : "");
			}
			printf("\n");
			chromaprint_dealloc(raw_fingerprint);
		}
		else {
			if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) {
				fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
				continue;
			}
			printf("FINGERPRINT=%s\n", fingerprint);
			chromaprint_dealloc(fingerprint);
		}
	}

	chromaprint_free(chromaprint_ctx);
	av_free(buffer1);
	av_free(buffer2);
	free(file_names);

	return 0;
}
Esempio n. 13
0
static int init_buffers(AVFilterLink *inlink, int nb_samples)
{
    AConvertContext *aconvert = inlink->dst->priv;
    AVFilterLink * const outlink = inlink->dst->outputs[0];
    int i, packed_stride = 0;
    const unsigned
        packing_conv = inlink->planar != outlink->planar &&
                       aconvert->out_nb_channels != 1,
        format_conv  = inlink->format != outlink->format;
    int nb_channels  = aconvert->out_nb_channels;

    uninit(inlink->dst);
    aconvert->max_nb_samples = nb_samples;

    if (aconvert->convert_chlayout) {
        /* allocate buffer for storing intermediary mixing samplesref */
        uint8_t *data[8];
        int linesize[8];
        int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);

        if (av_samples_alloc(data, linesize, nb_channels, nb_samples,
                             inlink->format, inlink->planar, 16) < 0)
            goto fail_no_mem;
        aconvert->mix_samplesref =
            avfilter_get_audio_buffer_ref_from_arrays(data, linesize, AV_PERM_WRITE,
                                                      nb_samples, inlink->format,
                                                      outlink->channel_layout,
                                                      inlink->planar);
        if (!aconvert->mix_samplesref)
            goto fail_no_mem;
    }

    // if there's a format/packing conversion we need an audio_convert context
    if (format_conv || packing_conv) {
        aconvert->out_samplesref =
            avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
        if (!aconvert->out_samplesref)
            goto fail_no_mem;

        aconvert->in_strides [0] = av_get_bytes_per_sample(inlink ->format);
        aconvert->out_strides[0] = av_get_bytes_per_sample(outlink->format);

        aconvert->out_conv = aconvert->out_samplesref->data;
        if (aconvert->mix_samplesref)
            aconvert->in_conv = aconvert->mix_samplesref->data;

        if (packing_conv) {
            // packed -> planar
            if (outlink->planar == AVFILTER_PLANAR) {
                if (aconvert->mix_samplesref)
                    aconvert->packed_data[0] = aconvert->mix_samplesref->data[0];
                aconvert->in_conv         = aconvert->packed_data;
                packed_stride             = aconvert->in_strides[0];
                aconvert->in_strides[0]  *= nb_channels;
            // planar -> packed
            } else {
                aconvert->packed_data[0]  = aconvert->out_samplesref->data[0];
                aconvert->out_conv        = aconvert->packed_data;
                packed_stride             = aconvert->out_strides[0];
                aconvert->out_strides[0] *= nb_channels;
            }
        } else if (outlink->planar == AVFILTER_PACKED) {
            /* If there's no packing conversion, and the stream is packed
             * then we treat the entire stream as one big channel
             */
            nb_channels = 1;
        }

        for (i = 1; i < nb_channels; i++) {
            aconvert->packed_data[i] = aconvert->packed_data[i-1] + packed_stride;
            aconvert->in_strides[i]  = aconvert->in_strides[0];
            aconvert->out_strides[i] = aconvert->out_strides[0];
        }

        aconvert->audioconvert_ctx =
                av_audio_convert_alloc(outlink->format, nb_channels,
                                       inlink->format,  nb_channels, NULL, 0);
        if (!aconvert->audioconvert_ctx)
            goto fail_no_mem;
    }

    return 0;

fail_no_mem:
    av_log(inlink->dst, AV_LOG_ERROR, "Could not allocate memory.\n");
    return AVERROR(ENOMEM);
}
Esempio n. 14
0
/**
 * Prepare filter for processing audio data of given format,
 * sample rate and number of channels.
 */
static int yae_reset(ATempoContext *atempo,
                     enum AVSampleFormat format,
                     int sample_rate,
                     int channels)
{
    const int sample_size = av_get_bytes_per_sample(format);
    uint32_t nlevels  = 0;
    uint32_t pot;
    int i;

    atempo->format   = format;
    atempo->channels = channels;
    atempo->stride   = sample_size * channels;

    // pick a segment window size:
    atempo->window = sample_rate / 24;

    // adjust window size to be a power-of-two integer:
    nlevels = av_log2(atempo->window);
    pot = 1 << nlevels;
    av_assert0(pot <= atempo->window);

    if (pot < atempo->window) {
        atempo->window = pot * 2;
        nlevels++;
    }

    // initialize audio fragment buffers:
    REALLOC_OR_FAIL(atempo->frag[0].data, atempo->window * atempo->stride);
    REALLOC_OR_FAIL(atempo->frag[1].data, atempo->window * atempo->stride);
    REALLOC_OR_FAIL(atempo->frag[0].xdat, atempo->window * sizeof(FFTComplex));
    REALLOC_OR_FAIL(atempo->frag[1].xdat, atempo->window * sizeof(FFTComplex));

    // initialize rDFT contexts:
    av_rdft_end(atempo->real_to_complex);
    atempo->real_to_complex = NULL;

    av_rdft_end(atempo->complex_to_real);
    atempo->complex_to_real = NULL;

    atempo->real_to_complex = av_rdft_init(nlevels + 1, DFT_R2C);
    if (!atempo->real_to_complex) {
        yae_release_buffers(atempo);
        return AVERROR(ENOMEM);
    }

    atempo->complex_to_real = av_rdft_init(nlevels + 1, IDFT_C2R);
    if (!atempo->complex_to_real) {
        yae_release_buffers(atempo);
        return AVERROR(ENOMEM);
    }

    REALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(FFTComplex));

    atempo->ring = atempo->window * 3;
    REALLOC_OR_FAIL(atempo->buffer, atempo->ring * atempo->stride);

    // initialize the Hann window function:
    REALLOC_OR_FAIL(atempo->hann, atempo->window * sizeof(float));

    for (i = 0; i < atempo->window; i++) {
        double t = (double)i / (double)(atempo->window - 1);
        double h = 0.5 * (1.0 - cos(2.0 * M_PI * t));
        atempo->hann[i] = (float)h;
    }

    yae_clear(atempo);
    return 0;
}
Esempio n. 15
0
int audio_decode(const char *filename, struct song *song) { // decode the track
	AVCodec *codec = NULL;
	AVCodecContext *c = NULL;
	AVFormatContext *pFormatCtx;
	
	//int8_t* sample_array;
	int i, d, e;
	int len;
	AVPacket avpkt;
	AVFrame *decoded_frame = NULL;
	int8_t *beginning;
	int got_frame;
	int audioStream;
	size_t index;

	av_register_all();
	av_init_packet(&avpkt);

	pFormatCtx = avformat_alloc_context();

	if(avformat_open_input(&pFormatCtx, filename, NULL, NULL) < 0) {
		printf("Couldn't open file: %s, %d\n", filename, errno);
		song->nSamples = 0;
		return 1;
	}

	if(avformat_find_stream_info(pFormatCtx, NULL) < 0) {
		printf("Couldn't find stream information\n");
		song->nSamples = 0;
		return 1;
	} 

	audioStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
	c = pFormatCtx->streams[audioStream]->codec;
	
	if (!codec) {
		printf("Codec not found!\n");
		song->nSamples = 0;
		return 1;
	}

	if(avcodec_open2(c, codec, NULL) < 0) {
		printf("Could not open codec\n");
		song->nSamples = 0;
		return 1;
	}
	
	song->sample_rate = c->sample_rate;
	song->duration = pFormatCtx->duration/AV_TIME_BASE;
	size = (((uint64_t)(pFormatCtx->duration)*(uint64_t)song->sample_rate)/(uint64_t)AV_TIME_BASE)*c->channels*av_get_bytes_per_sample(c->sample_fmt);
	song->nSamples = (((uint64_t)(pFormatCtx->duration)*(uint64_t)song->sample_rate)/(uint64_t)AV_TIME_BASE)*c->channels;
	song->sample_array = malloc(size);

	for(i = 0; i < song->nSamples; ++i)
		*(song->sample_array + i) = 0;

	beginning = song->sample_array;
	index = 0;

	song->planar = av_sample_fmt_is_planar(c->sample_fmt);
	song->nb_bytes_per_sample = av_get_bytes_per_sample(c->sample_fmt);

	song->channels = c->channels;
	
	song->artist = song->tracknumber = song->title = song->album = NULL;

	/* Get tags */
	if(av_dict_get(pFormatCtx->metadata, "track", NULL, AV_DICT_IGNORE_SUFFIX) != NULL) {
		song->tracknumber = malloc(strlen(av_dict_get(pFormatCtx->metadata, "TRACK", NULL, AV_DICT_IGNORE_SUFFIX)->value) + 1);
		strcpy(song->tracknumber, av_dict_get(pFormatCtx->metadata, "TRACK", NULL, AV_DICT_IGNORE_SUFFIX)->value);
		song->tracknumber[strcspn(song->tracknumber, "/")] = '\0';
	}
	else {
		song->tracknumber = malloc(1*sizeof(char));
		strcpy(song->tracknumber, "");
	}
	if(av_dict_get(pFormatCtx->metadata, "title", NULL, AV_DICT_IGNORE_SUFFIX) != NULL) {
		song->title = malloc(strlen(av_dict_get(pFormatCtx->metadata, "TITLE", NULL, AV_DICT_IGNORE_SUFFIX)->value) + 1);
		strcpy(song->title, av_dict_get(pFormatCtx->metadata, "TITLE", NULL, AV_DICT_IGNORE_SUFFIX)->value);
	}
	else {
		song->title = malloc(12*sizeof(char));
		strcpy(song->title, "<no title>");
	}
	if(av_dict_get(pFormatCtx->metadata, "ARTIST", NULL, AV_DICT_IGNORE_SUFFIX) != NULL) {
		song->artist= malloc(strlen(av_dict_get(pFormatCtx->metadata, "ARTIST", NULL, AV_DICT_IGNORE_SUFFIX)->value) + 1);
		strcpy(song->artist, av_dict_get(pFormatCtx->metadata, "ARTIST", NULL, AV_DICT_IGNORE_SUFFIX)->value);
	}
	else {
		song->artist= malloc(12*sizeof(char));
		strcpy(song->artist, "<no artist>");
	}
	if(av_dict_get(pFormatCtx->metadata, "ALBUM", NULL, AV_DICT_IGNORE_SUFFIX) != NULL) {
		song->album= malloc(strlen(av_dict_get(pFormatCtx->metadata, "ALBUM", NULL, AV_DICT_IGNORE_SUFFIX)->value) + 1);
		strcpy(song->album, av_dict_get(pFormatCtx->metadata, "ALBUM", NULL, AV_DICT_IGNORE_SUFFIX)->value);
	}
	else {
		song->album= malloc(11*sizeof(char));
		strcpy(song->album, "<no album>");
	}

	/* End of codec init */
	while(av_read_frame(pFormatCtx, &avpkt) >= 0) {
		if(avpkt.stream_index == audioStream) {
			got_frame = 0; 
		
			if(!decoded_frame) {
				if(!(decoded_frame = av_frame_alloc())) {
					printf("Could not allocate audio frame\n");
					exit(1);
				}
			}
			else 
				av_frame_unref(decoded_frame);

			len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
	
			if(len < 0) {
				//printf("Error while decoding\n");
				//exit(1);
				avpkt.size=0;
			}
			av_free_packet(&avpkt);
			/* interesting part: copying decoded data into a huge array */
			/* flac has a different behaviour from mp3, hence the planar condition */
			if(got_frame) {
				size_t data_size = av_samples_get_buffer_size(NULL, c->channels, decoded_frame->nb_samples, c->sample_fmt, 1); 

				if(index*song->nb_bytes_per_sample + data_size > size) {
					beginning = realloc(beginning, (size+=data_size));
					song->nSamples+=data_size/song->nb_bytes_per_sample;
				}
				int8_t *p = beginning+index*song->nb_bytes_per_sample;
				if(song->planar == 1) {
					for(i = 0; i < decoded_frame->nb_samples*song->nb_bytes_per_sample; i+=song->nb_bytes_per_sample) { 
						for(e = 0; e < c->channels; ++e)
							for(d = 0; d < song->nb_bytes_per_sample; ++d) 
								*(p++) = ((int8_t*)(decoded_frame->extended_data[e]))[i+d];
					}
					index+=data_size/song->nb_bytes_per_sample;
				}
				else if(song->planar == 0) {
					memcpy(index*song->nb_bytes_per_sample+beginning, decoded_frame->extended_data[0], data_size);
	        		index+=data_size/song->nb_bytes_per_sample; 
				}
			} 
		}
	}
	/* cleaning memory */

	avformat_close_input(&pFormatCtx);

	song->sample_array = beginning;
//	av_frame_free(&decoded_frame);
//	av_free_packet(&avpkt);

	return 0;
} 
Esempio n. 16
0
	virtual void cpu_task() override
	{
		while (true)
		{
			if (Emu.IsStopped() || is_closed)
			{
				break;
			}

			if (!job.pop(task, &is_closed))
			{
				break;
			}

			switch (task.type)
			{
			case adecStartSeq:
			{
				// TODO: reset data
				cellAdec.warning("adecStartSeq:");

				reader.addr = 0;
				reader.size = 0;
				reader.init = false;
				reader.has_ats = false;
				just_started = true;

				if (adecIsAtracX(type))
				{
					ch_cfg = task.at3p.channel_config;
					ch_out = task.at3p.channels;
					frame_size = task.at3p.frame_size;
					sample_rate = task.at3p.sample_rate;
					use_ats_headers = task.at3p.ats_header == 1;
				}
				break;
			}

			case adecEndSeq:
			{
				// TODO: finalize
				cellAdec.warning("adecEndSeq:");
				cbFunc(*this, id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, cbArg);

				just_finished = true;
				break;
			}

			case adecDecodeAu:
			{
				int err = 0;

				reader.addr = task.au.addr;
				reader.size = task.au.size;
				reader.has_ats = use_ats_headers;
				//LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);

				if (just_started)
				{
					first_pts = task.au.pts;
					last_pts = task.au.pts;
					if (adecIsAtracX(type)) last_pts -= 0x10000; // hack
				}

				struct AVPacketHolder : AVPacket
				{
					AVPacketHolder(u32 size)
					{
						av_init_packet(this);

						if (size)
						{
							data = (u8*)av_calloc(1, size + FF_INPUT_BUFFER_PADDING_SIZE);
							this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
						}
						else
						{
							data = NULL;
							size = 0;
						}
					}

					~AVPacketHolder()
					{
						av_free(data);
					}

				} au(0);

				if (just_started && just_finished)
				{
					avcodec_flush_buffers(ctx);
					
					reader.init = true; // wrong
					just_finished = false;
					just_started = false;
				}
				else if (just_started) // deferred initialization
				{
					AVDictionary* opts = nullptr;
					av_dict_set(&opts, "probesize", "96", 0);
					err = avformat_open_input(&fmt, NULL, input_format, &opts);
					if (err || opts)
					{
						throw EXCEPTION("avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
					}
					//err = avformat_find_stream_info(fmt, NULL);
					//if (err || !fmt->nb_streams)
					//{
					//	ADEC_ERROR("adecDecodeAu: avformat_find_stream_info() failed (err=0x%x, nb_streams=%d)", err, fmt->nb_streams);
					//}
					if (!avformat_new_stream(fmt, codec))
					{
						throw EXCEPTION("avformat_new_stream() failed");
					}
					ctx = fmt->streams[0]->codec; // TODO: check data

					opts = nullptr;
					av_dict_set(&opts, "refcounted_frames", "1", 0);
					{
						std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
						// not multithread-safe (???)
						err = avcodec_open2(ctx, codec, &opts);
					}
					if (err || opts)
					{
						throw EXCEPTION("avcodec_open2() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
					}
					just_started = false;
				}

				bool last_frame = false;

				while (true)
				{
					if (Emu.IsStopped() || is_closed)
					{
						if (Emu.IsStopped()) cellAdec.warning("adecDecodeAu: aborted");
						break;
					}

					last_frame = av_read_frame(fmt, &au) < 0;
					if (last_frame)
					{
						//break;
						av_free(au.data);
						au.data = NULL;
						au.size = 0;
					}

					struct AdecFrameHolder : AdecFrame
					{
						AdecFrameHolder()
						{
							data = av_frame_alloc();
						}

						~AdecFrameHolder()
						{
							if (data)
							{
								av_frame_unref(data);
								av_frame_free(&data);
							}
						}

					} frame;

					if (!frame.data)
					{
						throw EXCEPTION("av_frame_alloc() failed");
					}

					int got_frame = 0;

					int decode = avcodec_decode_audio4(ctx, frame.data, &got_frame, &au);

					if (decode <= 0)
					{
						if (decode < 0)
						{
							cellAdec.error("adecDecodeAu: AU decoding error(0x%x)", decode);
						}
						if (!got_frame && reader.size == 0) break;
					}

					if (got_frame)
					{
						//u64 ts = av_frame_get_best_effort_timestamp(frame.data);
						//if (ts != AV_NOPTS_VALUE)
						//{
						//	frame.pts = ts/* - first_pts*/;
						//	last_pts = frame.pts;
						//}
						last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate;
						frame.pts = last_pts;

						s32 nbps = av_get_bytes_per_sample((AVSampleFormat)frame.data->format);
						switch (frame.data->format)
						{
						case AV_SAMPLE_FMT_FLTP: break;
						case AV_SAMPLE_FMT_S16P: break;
						default:
						{
							throw EXCEPTION("Unsupported frame format(%d)", frame.data->format);
						}
						}
						frame.auAddr = task.au.addr;
						frame.auSize = task.au.size;
						frame.userdata = task.au.userdata;
						frame.size = frame.data->nb_samples * frame.data->channels * nbps;

						//LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
							//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps);

						if (frames.push(frame, &is_closed))
						{
							frame.data = nullptr; // to prevent destruction
							cbFunc(*this, id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, cbArg);
						}
					}
				}

				cbFunc(*this, id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, cbArg);
				break;
			}

			case adecClose:
			{
				break;
			}

			default:
			{
				throw EXCEPTION("Unknown task(%d)", (u32)task.type);
			}
			}
		}

		is_finished = true;
	}
Esempio n. 17
0
int avresample_open(AVAudioResampleContext *avr)
{
    int ret;

    /* set channel mixing parameters */
    avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
    if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
        av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
               avr->in_channel_layout);
        return AVERROR(EINVAL);
    }
    avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
    if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
        av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
               avr->out_channel_layout);
        return AVERROR(EINVAL);
    }
    avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
    avr->downmix_needed    = avr->in_channels  > avr->out_channels;
    avr->upmix_needed      = avr->out_channels > avr->in_channels ||
                             (!avr->downmix_needed && (avr->am->matrix ||
                              avr->in_channel_layout != avr->out_channel_layout));
    avr->mixing_needed     = avr->downmix_needed || avr->upmix_needed;

    /* set resampling parameters */
    avr->resample_needed   = avr->in_sample_rate != avr->out_sample_rate ||
                             avr->force_resampling;

    /* select internal sample format if not specified by the user */
    if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE &&
        (avr->mixing_needed || avr->resample_needed)) {
        enum AVSampleFormat  in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
        enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
        int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
                            av_get_bytes_per_sample(out_fmt));
        if (max_bps <= 2) {
            avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
        } else if (avr->mixing_needed) {
            avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
        } else {
            if (max_bps <= 4) {
                if (in_fmt  == AV_SAMPLE_FMT_S32P ||
                    out_fmt == AV_SAMPLE_FMT_S32P) {
                    if (in_fmt  == AV_SAMPLE_FMT_FLTP ||
                        out_fmt == AV_SAMPLE_FMT_FLTP) {
                        /* if one is s32 and the other is flt, use dbl */
                        avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
                    } else {
                        /* if one is s32 and the other is s32, s16, or u8, use s32 */
                        avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P;
                    }
                } else {
                    /* if one is flt and the other is flt, s16 or u8, use flt */
                    avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
                }
            } else {
                /* if either is dbl, use dbl */
                avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
            }
        }
        av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n",
               av_get_sample_fmt_name(avr->internal_sample_fmt));
    }

    /* set sample format conversion parameters */
    if (avr->in_channels == 1)
        avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
    if (avr->out_channels == 1)
        avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
    avr->in_convert_needed = (avr->resample_needed || avr->mixing_needed) &&
                              avr->in_sample_fmt != avr->internal_sample_fmt;
    if (avr->resample_needed || avr->mixing_needed)
        avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
    else
        avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;

    /* allocate buffers */
    if (avr->mixing_needed || avr->in_convert_needed) {
        avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
                                             0, avr->internal_sample_fmt,
                                             "in_buffer");
        if (!avr->in_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    if (avr->resample_needed) {
        avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
                                                       0, avr->internal_sample_fmt,
                                                       "resample_out_buffer");
        if (!avr->resample_out_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    if (avr->out_convert_needed) {
        avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
                                              avr->out_sample_fmt, "out_buffer");
        if (!avr->out_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
                                        1024);
    if (!avr->out_fifo) {
        ret = AVERROR(ENOMEM);
        goto error;
    }

    /* setup contexts */
    if (avr->in_convert_needed) {
        avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
                                            avr->in_sample_fmt, avr->in_channels);
        if (!avr->ac_in) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->out_convert_needed) {
        enum AVSampleFormat src_fmt;
        if (avr->in_convert_needed)
            src_fmt = avr->internal_sample_fmt;
        else
            src_fmt = avr->in_sample_fmt;
        avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
                                             avr->out_channels);
        if (!avr->ac_out) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->resample_needed) {
        avr->resample = ff_audio_resample_init(avr);
        if (!avr->resample) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->mixing_needed) {
        ret = ff_audio_mix_init(avr);
        if (ret < 0)
            goto error;
    }

    return 0;

error:
    avresample_close(avr);
    return ret;
}
Esempio n. 18
0
void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) {
	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
	if (!encoder->context || !encoder->audioCodec) {
		return;
	}

	if (encoder->absf && !left) {
		// XXX: AVBSF doesn't like silence. Figure out why.
		left = 1;
	}

	encoder->audioBuffer[encoder->currentAudioSample * 2] = left;
	encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right;

	++encoder->currentAudioSample;

	if (encoder->currentAudioSample * 4 < encoder->audioBufferSize) {
		return;
	}

	int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
	encoder->currentAudioSample = 0;
#ifdef USE_LIBAVRESAMPLE
	avresample_convert(encoder->resampleContext, 0, 0, 0,
	                   (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);

	if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
		return;
	}
#if LIBAVCODEC_VERSION_MAJOR >= 55
	av_frame_make_writable(encoder->audioFrame);
#endif
	int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
#else
#if LIBAVCODEC_VERSION_MAJOR >= 55
	av_frame_make_writable(encoder->audioFrame);
#endif
	if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) {
		swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
		return;
	}
	int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize,
	                          (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
#endif

	encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base);
	encoder->currentAudioFrame += samples;

	AVPacket packet;
	av_init_packet(&packet);
	packet.data = 0;
	packet.size = 0;
	packet.pts = encoder->audioFrame->pts;

	int gotData;
#ifdef FFMPEG_USE_PACKETS
	avcodec_send_frame(encoder->audio, encoder->audioFrame);
	gotData = avcodec_receive_packet(encoder->audio, &packet);
	gotData = (gotData == 0) && packet.size;
#else
	avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData);
#endif
	if (gotData) {
		if (encoder->absf) {
			AVPacket tempPacket;

#ifdef FFMPEG_USE_NEW_BSF
			int success = av_bsf_send_packet(encoder->absf, &packet);
			if (success >= 0) {
				success = av_bsf_receive_packet(encoder->absf, &tempPacket);
			}
#else
			int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0,
			    &tempPacket.data, &tempPacket.size,
			    packet.data, packet.size, 0);
#endif

			if (success >= 0) {
#if LIBAVUTIL_VERSION_MAJOR >= 53
				tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0);
#endif

#ifdef FFMPEG_USE_PACKET_UNREF
				av_packet_move_ref(&packet, &tempPacket);
#else
				av_free_packet(&packet);
				packet = tempPacket;
#endif

				packet.stream_index = encoder->audioStream->index;
				av_interleaved_write_frame(encoder->context, &packet);
			}
		} else {
			packet.stream_index = encoder->audioStream->index;
			av_interleaved_write_frame(encoder->context, &packet);
		}
	}
#ifdef FFMPEG_USE_PACKET_UNREF
	av_packet_unref(&packet);
#else
	av_free_packet(&packet);
#endif
}
Esempio n. 19
0
av_cold int swr_init(struct SwrContext *s){
    int ret;
    char l1[1024], l2[1024];

    clear_context(s);

    if(s-> in_sample_fmt >= AV_SAMPLE_FMT_NB){
        av_log(s, AV_LOG_ERROR, "Requested input sample format %d is invalid\n", s->in_sample_fmt);
        return AVERROR(EINVAL);
    }
    if(s->out_sample_fmt >= AV_SAMPLE_FMT_NB){
        av_log(s, AV_LOG_ERROR, "Requested output sample format %d is invalid\n", s->out_sample_fmt);
        return AVERROR(EINVAL);
    }

    s->out.ch_count  = s-> user_out_ch_count;
    s-> in.ch_count  = s->  user_in_ch_count;
    s->used_ch_count = s->user_used_ch_count;

    s-> in_ch_layout = s-> user_in_ch_layout;
    s->out_ch_layout = s->user_out_ch_layout;

    s->int_sample_fmt= s->user_int_sample_fmt;

    if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) {
        av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout);
        s->in_ch_layout = 0;
    }

    if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) {
        av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout);
        s->out_ch_layout = 0;
    }

    switch(s->engine){
#if CONFIG_LIBSOXR
        case SWR_ENGINE_SOXR: s->resampler = &swri_soxr_resampler; break;
#endif
        case SWR_ENGINE_SWR : s->resampler = &swri_resampler; break;
        default:
            av_log(s, AV_LOG_ERROR, "Requested resampling engine is unavailable\n");
            return AVERROR(EINVAL);
    }

    if(!s->used_ch_count)
        s->used_ch_count= s->in.ch_count;

    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
        av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
        s-> in_ch_layout= 0;
    }

    if(!s-> in_ch_layout)
        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
    if(!s->out_ch_layout)
        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);

    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0 ||
                 s->rematrix_custom;

    if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
        if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2
           && av_get_bytes_per_sample(s->out_sample_fmt) <= 2){
            s->int_sample_fmt= AV_SAMPLE_FMT_S16P;
        }else if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2
           && !s->rematrix
           && s->out_sample_rate==s->in_sample_rate
           && !(s->flags & SWR_FLAG_RESAMPLE)){
            s->int_sample_fmt= AV_SAMPLE_FMT_S16P;
        }else if(   av_get_planar_sample_fmt(s-> in_sample_fmt) == AV_SAMPLE_FMT_S32P
                 && av_get_planar_sample_fmt(s->out_sample_fmt) == AV_SAMPLE_FMT_S32P
                 && !s->rematrix
                 && s->engine != SWR_ENGINE_SOXR){
            s->int_sample_fmt= AV_SAMPLE_FMT_S32P;
        }else if(av_get_bytes_per_sample(s->in_sample_fmt) <= 4){
            s->int_sample_fmt= AV_SAMPLE_FMT_FLTP;
        }else{
            s->int_sample_fmt= AV_SAMPLE_FMT_DBLP;
        }
    }
    av_log(s, AV_LOG_DEBUG, "Using %s internally between filters\n", av_get_sample_fmt_name(s->int_sample_fmt));

    if(   s->int_sample_fmt != AV_SAMPLE_FMT_S16P
        &&s->int_sample_fmt != AV_SAMPLE_FMT_S32P
        &&s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
        &&s->int_sample_fmt != AV_SAMPLE_FMT_DBLP){
        av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, S16/S32/FLT/DBL is supported\n", av_get_sample_fmt_name(s->int_sample_fmt));
        return AVERROR(EINVAL);
    }

    set_audiodata_fmt(&s-> in, s-> in_sample_fmt);
    set_audiodata_fmt(&s->out, s->out_sample_fmt);

    if (s->firstpts_in_samples != AV_NOPTS_VALUE) {
        if (!s->async && s->min_compensation >= FLT_MAX/2)
            s->async = 1;
        s->firstpts =
        s->outpts   = s->firstpts_in_samples * s->out_sample_rate;
    } else
        s->firstpts = AV_NOPTS_VALUE;

    if (s->async) {
        if (s->min_compensation >= FLT_MAX/2)
            s->min_compensation = 0.001;
        if (s->async > 1.0001) {
            s->max_soft_compensation = s->async / (double) s->in_sample_rate;
        }
    }

    if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
        s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta, s->precision, s->cheby);
        if (!s->resample) {
            av_log(s, AV_LOG_ERROR, "Failed to initialize resampler\n");
            return AVERROR(ENOMEM);
        }
    }else
        s->resampler->free(&s->resample);
    if(    s->int_sample_fmt != AV_SAMPLE_FMT_S16P
        && s->int_sample_fmt != AV_SAMPLE_FMT_S32P
        && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
        && s->int_sample_fmt != AV_SAMPLE_FMT_DBLP
        && s->resample){
        av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16/s32/flt/dbl\n");
        ret = AVERROR(EINVAL);
        goto fail;
    }

#define RSC 1 //FIXME finetune
    if(!s-> in.ch_count)
        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
    if(!s->used_ch_count)
        s->used_ch_count= s->in.ch_count;
    if(!s->out.ch_count)
        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);

    if(!s-> in.ch_count){
        av_assert0(!s->in_ch_layout);
        av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
        ret = AVERROR(EINVAL);
        goto fail;
    }

    av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout);
    av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout);
    if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) {
        av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count);
        ret = AVERROR(EINVAL);
        goto fail;
    }
    if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) {
        av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count);
        ret = AVERROR(EINVAL);
        goto fail;
    }

    if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) {
        av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s "
               "but there is not enough information to do it\n", l1, l2);
        ret = AVERROR(EINVAL);
        goto fail;
    }

av_assert0(s->used_ch_count);
av_assert0(s->out.ch_count);
    s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;

    s->in_buffer= s->in;
    s->silence  = s->in;
    s->drop_temp= s->out;

    if(!s->resample && !s->rematrix && !s->channel_map && !s->dither.method){
        s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt,
                                                   s-> in_sample_fmt, s-> in.ch_count, NULL, 0);
        return 0;
    }

    s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt,
                                             s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0);
    s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt,
                                             s->int_sample_fmt, s->out.ch_count, NULL, 0);

    if (!s->in_convert || !s->out_convert) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }

    s->postin= s->in;
    s->preout= s->out;
    s->midbuf= s->in;

    if(s->channel_map){
        s->postin.ch_count=
        s->midbuf.ch_count= s->used_ch_count;
        if(s->resample)
            s->in_buffer.ch_count= s->used_ch_count;
    }
    if(!s->resample_first){
        s->midbuf.ch_count= s->out.ch_count;
        if(s->resample)
            s->in_buffer.ch_count = s->out.ch_count;
    }

    set_audiodata_fmt(&s->postin, s->int_sample_fmt);
    set_audiodata_fmt(&s->midbuf, s->int_sample_fmt);
    set_audiodata_fmt(&s->preout, s->int_sample_fmt);

    if(s->resample){
        set_audiodata_fmt(&s->in_buffer, s->int_sample_fmt);
    }

    if ((ret = swri_dither_init(s, s->out_sample_fmt, s->int_sample_fmt)) < 0)
        goto fail;

    if(s->rematrix || s->dither.method) {
        ret = swri_rematrix_init(s);
        if (ret < 0)
            goto fail;
    }

    return 0;
fail:
    swr_close(s);
    return ret;

}
Esempio n. 20
0
hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt,
                                            int hb_amixdown, int normalize_mix)
{
    hb_audio_resample_t *resample = calloc(1, sizeof(hb_audio_resample_t));
    if (resample == NULL)
    {
        hb_error("hb_audio_resample_init: failed to allocate resample");
        goto fail;
    }

    // avresample context, initialized in hb_audio_resample_update()
    resample->avresample = NULL;

    // we don't support planar output yet
    if (av_sample_fmt_is_planar(sample_fmt))
    {
        hb_error("hb_audio_resample_init: planar output not supported ('%s')",
                 av_get_sample_fmt_name(sample_fmt));
        goto fail;
    }

    // convert mixdown to channel_layout/matrix_encoding combo
    int matrix_encoding;
    uint64_t channel_layout = hb_ff_mixdown_xlat(hb_amixdown, &matrix_encoding);

    /*
     * When downmixing, Dual Mono to Mono is a special case:
     * the audio must remain 2-channel until all conversions are done.
     */
    if (hb_amixdown == HB_AMIXDOWN_LEFT || hb_amixdown == HB_AMIXDOWN_RIGHT)
    {
        channel_layout                 = AV_CH_LAYOUT_STEREO;
        resample->dual_mono_downmix    = 1;
        resample->dual_mono_right_only = (hb_amixdown == HB_AMIXDOWN_RIGHT);
    }
    else
    {
        resample->dual_mono_downmix = 0;
    }

    // requested output channel_layout, sample_fmt
    resample->out.channels = av_get_channel_layout_nb_channels(channel_layout);
    resample->out.channel_layout      = channel_layout;
    resample->out.matrix_encoding     = matrix_encoding;
    resample->out.normalize_mix_level = normalize_mix;
    resample->out.sample_fmt          = sample_fmt;
    resample->out.sample_size         = av_get_bytes_per_sample(sample_fmt);

    // set default input characteristics
    resample->in.sample_fmt         = resample->out.sample_fmt;
    resample->in.channel_layout     = resample->out.channel_layout;
    resample->in.center_mix_level   = HB_MIXLEV_DEFAULT;
    resample->in.surround_mix_level = HB_MIXLEV_DEFAULT;

    // by default, no conversion needed
    resample->resample_needed = 0;
    return resample;

fail:
    hb_audio_resample_free(resample);
    return NULL;
}
Esempio n. 21
0
int swr_init(struct SwrContext *s){
    s->in_buffer_index= 0;
    s->in_buffer_count= 0;
    s->resample_in_constraint= 0;
    free_temp(&s->postin);
    free_temp(&s->midbuf);
    free_temp(&s->preout);
    free_temp(&s->in_buffer);
    swri_audio_convert_free(&s-> in_convert);
    swri_audio_convert_free(&s->out_convert);
    swri_audio_convert_free(&s->full_convert);

    s-> in.planar= av_sample_fmt_is_planar(s-> in_sample_fmt);
    s->out.planar= av_sample_fmt_is_planar(s->out_sample_fmt);
    s-> in_sample_fmt= av_get_alt_sample_fmt(s-> in_sample_fmt, 0);
    s->out_sample_fmt= av_get_alt_sample_fmt(s->out_sample_fmt, 0);

    if(s-> in_sample_fmt >= AV_SAMPLE_FMT_NB){
        av_log(s, AV_LOG_ERROR, "Requested input sample format %d is invalid\n", s->in_sample_fmt);
        return AVERROR(EINVAL);
    }
    if(s->out_sample_fmt >= AV_SAMPLE_FMT_NB){
        av_log(s, AV_LOG_ERROR, "Requested output sample format %d is invalid\n", s->out_sample_fmt);
        return AVERROR(EINVAL);
    }

    if(   s->int_sample_fmt != AV_SAMPLE_FMT_S16
        &&s->int_sample_fmt != AV_SAMPLE_FMT_FLT){
        av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, only float & S16 is supported\n", av_get_sample_fmt_name(s->int_sample_fmt));
        return AVERROR(EINVAL);
    }

    //FIXME should we allow/support using FLT on material that doesnt need it ?
    if(s->in_sample_fmt <= AV_SAMPLE_FMT_S16 || s->int_sample_fmt==AV_SAMPLE_FMT_S16){
        s->int_sample_fmt= AV_SAMPLE_FMT_S16;
    }else
        s->int_sample_fmt= AV_SAMPLE_FMT_FLT;


    if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
        s->resample = swri_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, 16, 10, 0, 0.8);
    }else
        swri_resample_free(&s->resample);
    if(s->int_sample_fmt != AV_SAMPLE_FMT_S16 && s->resample){
        av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16 currently\n"); //FIXME
        return -1;
    }

    if(!s->used_ch_count)
        s->used_ch_count= s->in.ch_count;

    if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
        av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
        s-> in_ch_layout= 0;
    }

    if(!s-> in_ch_layout)
        s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
    if(!s->out_ch_layout)
        s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);

    s->rematrix= s->out_ch_layout  !=s->in_ch_layout || s->rematrix_volume!=1.0;

#define RSC 1 //FIXME finetune
    if(!s-> in.ch_count)
        s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
    if(!s->used_ch_count)
        s->used_ch_count= s->in.ch_count;
    if(!s->out.ch_count)
        s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);

    if(!s-> in.ch_count){
        av_assert0(!s->in_ch_layout);
        av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n");
        return -1;
    }

av_assert0(s->used_ch_count);
av_assert0(s->out.ch_count);
    s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;

    s-> in.bps= av_get_bytes_per_sample(s-> in_sample_fmt);
    s->int_bps= av_get_bytes_per_sample(s->int_sample_fmt);
    s->out.bps= av_get_bytes_per_sample(s->out_sample_fmt);

    if(!s->resample && !s->rematrix && !s->channel_map){
        s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt,
                                                   s-> in_sample_fmt, s-> in.ch_count, NULL, 0);
        return 0;
    }

    s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt,
                                             s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0);
    s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt,
                                             s->int_sample_fmt, s->out.ch_count, NULL, 0);


    s->postin= s->in;
    s->preout= s->out;
    s->midbuf= s->in;
    s->in_buffer= s->in;
    if(s->channel_map){
        s->postin.ch_count=
        s->midbuf.ch_count=
        s->in_buffer.ch_count= s->used_ch_count;
    }
    if(!s->resample_first){
        s->midbuf.ch_count= s->out.ch_count;
        s->in_buffer.ch_count = s->out.ch_count;
    }

    s->in_buffer.bps = s->postin.bps = s->midbuf.bps = s->preout.bps =  s->int_bps;
    s->in_buffer.planar = s->postin.planar = s->midbuf.planar = s->preout.planar =  1;


    if(s->rematrix)
        return swri_rematrix_init(s);

    return 0;
}
Esempio n. 22
0
int avresample_open(AVAudioResampleContext *avr)
{
    int ret;

    if (avresample_is_open(avr)) {
        av_log(avr, AV_LOG_ERROR, "The resampling context is already open.\n");
        return AVERROR(EINVAL);
    }

    /* set channel mixing parameters */
    avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
    if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
        av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
               avr->in_channel_layout);
        return AVERROR(EINVAL);
    }
    avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
    if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
        av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
               avr->out_channel_layout);
        return AVERROR(EINVAL);
    }
    avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
    avr->downmix_needed    = avr->in_channels  > avr->out_channels;
    avr->upmix_needed      = avr->out_channels > avr->in_channels ||
                             (!avr->downmix_needed && (avr->mix_matrix ||
                              avr->in_channel_layout != avr->out_channel_layout));
    avr->mixing_needed     = avr->downmix_needed || avr->upmix_needed;

    /* set resampling parameters */
    avr->resample_needed   = avr->in_sample_rate != avr->out_sample_rate ||
                             avr->force_resampling;

    /* select internal sample format if not specified by the user */
    if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE &&
        (avr->mixing_needed || avr->resample_needed)) {
        enum AVSampleFormat  in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
        enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
        int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
                            av_get_bytes_per_sample(out_fmt));
        if (max_bps <= 2) {
            avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
        } else if (avr->mixing_needed) {
            avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
        } else {
            if (max_bps <= 4) {
                if (in_fmt  == AV_SAMPLE_FMT_S32P ||
                    out_fmt == AV_SAMPLE_FMT_S32P) {
                    if (in_fmt  == AV_SAMPLE_FMT_FLTP ||
                        out_fmt == AV_SAMPLE_FMT_FLTP) {
                        /* if one is s32 and the other is flt, use dbl */
                        avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
                    } else {
                        /* if one is s32 and the other is s32, s16, or u8, use s32 */
                        avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P;
                    }
                } else {
                    /* if one is flt and the other is flt, s16 or u8, use flt */
                    avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
                }
            } else {
                /* if either is dbl, use dbl */
                avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
            }
        }
        av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n",
               av_get_sample_fmt_name(avr->internal_sample_fmt));
    }

    /* treat all mono as planar for easier comparison */
    if (avr->in_channels == 1)
        avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
    if (avr->out_channels == 1)
        avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);

    /* we may need to add an extra conversion in order to remap channels if
       the output format is not planar */
    if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
        !av_sample_fmt_is_planar(avr->out_sample_fmt)) {
        avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
    }

    /* set sample format conversion parameters */
    if (avr->resample_needed || avr->mixing_needed)
        avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
    else
        avr->in_convert_needed = avr->use_channel_map &&
                                 !av_sample_fmt_is_planar(avr->out_sample_fmt);

    if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
        avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
    else
        avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;

    avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed ||
                          (avr->use_channel_map && avr->resample_needed));

    if (avr->use_channel_map) {
        if (avr->in_copy_needed) {
            avr->remap_point = REMAP_IN_COPY;
            av_dlog(avr, "remap channels during in_copy\n");
        } else if (avr->in_convert_needed) {
            avr->remap_point = REMAP_IN_CONVERT;
            av_dlog(avr, "remap channels during in_convert\n");
        } else if (avr->out_convert_needed) {
            avr->remap_point = REMAP_OUT_CONVERT;
            av_dlog(avr, "remap channels during out_convert\n");
        } else {
            avr->remap_point = REMAP_OUT_COPY;
            av_dlog(avr, "remap channels during out_copy\n");
        }

#ifdef DEBUG
        {
            int ch;
            av_dlog(avr, "output map: ");
            if (avr->ch_map_info.do_remap)
                for (ch = 0; ch < avr->in_channels; ch++)
                    av_dlog(avr, " % 2d", avr->ch_map_info.channel_map[ch]);
            else
                av_dlog(avr, "n/a");
            av_dlog(avr, "\n");
            av_dlog(avr, "copy map:   ");
            if (avr->ch_map_info.do_copy)
                for (ch = 0; ch < avr->in_channels; ch++)
                    av_dlog(avr, " % 2d", avr->ch_map_info.channel_copy[ch]);
            else
                av_dlog(avr, "n/a");
            av_dlog(avr, "\n");
            av_dlog(avr, "zero map:   ");
            if (avr->ch_map_info.do_zero)
                for (ch = 0; ch < avr->in_channels; ch++)
                    av_dlog(avr, " % 2d", avr->ch_map_info.channel_zero[ch]);
            else
                av_dlog(avr, "n/a");
            av_dlog(avr, "\n");
            av_dlog(avr, "input map:  ");
            for (ch = 0; ch < avr->in_channels; ch++)
                av_dlog(avr, " % 2d", avr->ch_map_info.input_map[ch]);
            av_dlog(avr, "\n");
        }
#endif
    } else
        avr->remap_point = REMAP_NONE;

    /* allocate buffers */
    if (avr->in_copy_needed || avr->in_convert_needed) {
        avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
                                             0, avr->internal_sample_fmt,
                                             "in_buffer");
        if (!avr->in_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    if (avr->resample_needed) {
        avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
                                                       1024, avr->internal_sample_fmt,
                                                       "resample_out_buffer");
        if (!avr->resample_out_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    if (avr->out_convert_needed) {
        avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
                                              avr->out_sample_fmt, "out_buffer");
        if (!avr->out_buffer) {
            ret = AVERROR(EINVAL);
            goto error;
        }
    }
    avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
                                        1024);
    if (!avr->out_fifo) {
        ret = AVERROR(ENOMEM);
        goto error;
    }

    /* setup contexts */
    if (avr->in_convert_needed) {
        avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
                                            avr->in_sample_fmt, avr->in_channels,
                                            avr->in_sample_rate,
                                            avr->remap_point == REMAP_IN_CONVERT);
        if (!avr->ac_in) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->out_convert_needed) {
        enum AVSampleFormat src_fmt;
        if (avr->in_convert_needed)
            src_fmt = avr->internal_sample_fmt;
        else
            src_fmt = avr->in_sample_fmt;
        avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
                                             avr->out_channels,
                                             avr->out_sample_rate,
                                             avr->remap_point == REMAP_OUT_CONVERT);
        if (!avr->ac_out) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->resample_needed) {
        avr->resample = ff_audio_resample_init(avr);
        if (!avr->resample) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }
    if (avr->mixing_needed) {
        avr->am = ff_audio_mix_alloc(avr);
        if (!avr->am) {
            ret = AVERROR(ENOMEM);
            goto error;
        }
    }

    return 0;

error:
    avresample_close(avr);
    return ret;
}
Esempio n. 23
0
int decode_audio(AVCodecContext  *ctx, queue_t *qa)
{
    static struct SwrContext *swr_ctx;
    static int64_t src_layout;
    static int src_freq;
    static int src_channels;
    static enum AVSampleFormat src_fmt = -1;
    static AVFrame *aFrame;

    AVPacket   pkt;
    AVPacket    pkt_tmp;
    int64_t dec_channel_layout;
    int len, len2;
    int got_frame;
    int data_size;


    if( astream.count > 192000*2)
        return -1;

    if( get_packet(qa, &pkt) == 0 )
        return 0;

 //          __asm__("int3");

    if (!aFrame)
    {
        if (!(aFrame = avcodec_alloc_frame()))
            return -1;
    } else
        avcodec_get_frame_defaults(aFrame);

    pkt_tmp = pkt;

    while(pkt_tmp.size > 0)
    {
        data_size = 192000;

//        len = avcodec_decode_audio3(ctx,(int16_t*)decoder_buffer,
//                                   &data_size, &pkt_tmp);
        got_frame = 0;
        len = avcodec_decode_audio4(ctx, aFrame, &got_frame, &pkt_tmp);

        if(len >= 0 && got_frame)
        {
            char *samples;
            int ch, plane_size;
            int planar    = av_sample_fmt_is_planar(ctx->sample_fmt);
            int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels,
                                                   aFrame->nb_samples,
                                                   ctx->sample_fmt, 1);

//            if(audio_base == -1.0)
//            {
//                if (pkt.pts != AV_NOPTS_VALUE)
//                    audio_base = get_audio_base() * pkt.pts;
//                printf("audio base %f\n", audio_base);
//            };

            pkt_tmp.data += len;
            pkt_tmp.size -= len;

            dec_channel_layout =
                (aFrame->channel_layout && aFrame->channels == av_get_channel_layout_nb_channels(aFrame->channel_layout)) ?
                aFrame->channel_layout : av_get_default_channel_layout(aFrame->channels);

            if (aFrame->format          != src_fmt     ||
                dec_channel_layout      != src_layout  ||
                aFrame->sample_rate     != src_freq    ||
                !swr_ctx)
            {
                swr_free(&swr_ctx);
                swr_ctx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16,
                                             aFrame->sample_rate, dec_channel_layout,aFrame->format,
                                             aFrame->sample_rate, 0, NULL);
                if (!swr_ctx || swr_init(swr_ctx) < 0)
                {
                    printf("Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
                        aFrame->sample_rate,   av_get_sample_fmt_name(aFrame->format), (int)aFrame->channels,
                        aFrame->sample_rate, av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 2);
                    break;
                }

                src_layout   = dec_channel_layout;
                src_channels = aFrame->channels;
                src_freq     = aFrame->sample_rate;
                src_fmt      = aFrame->format;
            };

            if (swr_ctx)
            {
                const uint8_t **in = (const uint8_t **)aFrame->extended_data;
                uint8_t *out[] = {decoder_buffer};
                int out_count = 192000 * 3 / 2 / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
                len2 = swr_convert(swr_ctx, out, out_count, in, aFrame->nb_samples);
                if (len2 < 0) {
                    printf("swr_convert() failed\n");
                    break;
                }
                if (len2 == out_count) {
                    printf("warning: audio buffer is probably too small\n");
                    swr_init(swr_ctx);
                }
                data_size = len2 * 2 * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);

                mutex_lock(&astream.lock);

                samples = astream.buffer+astream.count;

                memcpy(samples, decoder_buffer, data_size);
/*
            memcpy(samples, aFrame->extended_data[0], plane_size);

            if (planar && ctx->channels > 1)
            {
                uint8_t *out = ((uint8_t *)samples) + plane_size;
                for (ch = 1; ch < ctx->channels; ch++)
                {
                    memcpy(out, aFrame->extended_data[ch], plane_size);
                    out += plane_size;
                }
            }
*/
                astream.count += data_size;
                mutex_unlock(&astream.lock);
            };
       }
       else pkt_tmp.size = 0;
    }
    av_free_packet(&pkt);
    return 1;
};
Esempio n. 24
0
File: dither.c Progetto: 1c0n/xbmc
int swri_dither_init(SwrContext *s, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt)
{
    int i;
    double scale = 0;

    if (s->dither.method > SWR_DITHER_TRIANGULAR_HIGHPASS && s->dither.method <= SWR_DITHER_NS)
        return AVERROR(EINVAL);

    out_fmt = av_get_packed_sample_fmt(out_fmt);
    in_fmt  = av_get_packed_sample_fmt( in_fmt);

    if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){
        if(out_fmt == AV_SAMPLE_FMT_S32) scale = 1.0/(1L<<31);
        if(out_fmt == AV_SAMPLE_FMT_S16) scale = 1.0/(1L<<15);
        if(out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1.0/(1L<< 7);
    }
    if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S16) scale = 1L<<16;
    if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24;
    if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8;

    scale *= s->dither.scale;

    if (out_fmt == AV_SAMPLE_FMT_S32 && s->dither.output_sample_bits)
        scale *= 1<<(32-s->dither.output_sample_bits);

    s->dither.ns_pos = 0;
    s->dither.noise_scale=   scale;
    s->dither.ns_scale   =   scale;
    s->dither.ns_scale_1 = scale ? 1/scale : 0;
    memset(s->dither.ns_errors, 0, sizeof(s->dither.ns_errors));
    for (i=0; filters[i].coefs; i++) {
        const filter_t *f = &filters[i];
        if (fabs(s->out_sample_rate - f->rate) / f->rate <= .05 && f->name == s->dither.method) {
            int j;
            s->dither.ns_taps = f->len;
            for (j=0; j<f->len; j++)
                s->dither.ns_coeffs[j] = f->coefs[j];
            s->dither.ns_scale_1 *= 1 - exp(f->gain_cB * M_LN10 * 0.005) * 2 / (1<<(8*av_get_bytes_per_sample(out_fmt)));
            break;
        }
    }
    if (!filters[i].coefs && s->dither.method > SWR_DITHER_NS) {
        av_log(s, AV_LOG_WARNING, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n");
        s->dither.method = SWR_DITHER_TRIANGULAR_HIGHPASS;
    }

    av_assert0(!s->preout.count);
    s->dither.noise = s->preout;
    s->dither.temp  = s->preout;
    if (s->dither.method > SWR_DITHER_NS) {
        s->dither.noise.bps = 4;
        s->dither.noise.fmt = AV_SAMPLE_FMT_FLTP;
        s->dither.noise_scale = 1;
    }

    return 0;
}
Esempio n. 25
0
DitherContext *ff_dither_alloc(AVAudioResampleContext *avr,
                               enum AVSampleFormat out_fmt,
                               enum AVSampleFormat in_fmt,
                               int channels, int sample_rate)
{
    AVLFG seed_gen;
    DitherContext *c;
    int ch;

    if (av_get_packed_sample_fmt(out_fmt) != AV_SAMPLE_FMT_S16 ||
            av_get_bytes_per_sample(in_fmt) <= 2) {
        av_log(avr, AV_LOG_ERROR, "dithering %s to %s is not supported\n",
               av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt));
        return NULL;
    }

    c = av_mallocz(sizeof(*c));
    if (!c)
        return NULL;

    if (avr->dither_method == AV_RESAMPLE_DITHER_TRIANGULAR_NS &&
            sample_rate != 48000 && sample_rate != 44100) {
        av_log(avr, AV_LOG_WARNING, "sample rate must be 48000 or 44100 Hz "
               "for triangular_ns dither. using triangular_hp instead.\n");
        avr->dither_method = AV_RESAMPLE_DITHER_TRIANGULAR_HP;
    }
    c->method = avr->dither_method;
    dither_init(&c->ddsp, c->method);

    if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) {
        if (sample_rate == 48000) {
            c->ns_coef_b = ns_48_coef_b;
            c->ns_coef_a = ns_48_coef_a;
        } else {
            c->ns_coef_b = ns_44_coef_b;
            c->ns_coef_a = ns_44_coef_a;
        }
    }

    /* Either s16 or s16p output format is allowed, but s16p is used
       internally, so we need to use a temp buffer and interleave if the output
       format is s16 */
    if (out_fmt != AV_SAMPLE_FMT_S16P) {
        c->s16_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_S16P,
                                          "dither s16 buffer");
        if (!c->s16_data)
            goto fail;

        c->ac_out = ff_audio_convert_alloc(avr, out_fmt, AV_SAMPLE_FMT_S16P,
                                           channels, sample_rate);
        if (!c->ac_out)
            goto fail;
    }

    if (in_fmt != AV_SAMPLE_FMT_FLTP) {
        c->flt_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_FLTP,
                                          "dither flt buffer");
        if (!c->flt_data)
            goto fail;

        c->ac_in = ff_audio_convert_alloc(avr, AV_SAMPLE_FMT_FLTP, in_fmt,
                                          channels, sample_rate);
        if (!c->ac_in)
            goto fail;
    }

    c->state = av_mallocz(channels * sizeof(*c->state));
    if (!c->state)
        goto fail;
    c->channels = channels;

    /* calculate thresholds for turning off dithering during periods of
       silence to avoid replacing digital silence with quiet dither noise */
    c->mute_dither_threshold = lrintf(sample_rate * MUTE_THRESHOLD_SEC);
    c->mute_reset_threshold  = c->mute_dither_threshold * 4;

    /* initialize dither states */
    av_lfg_init(&seed_gen, 0xC0FFEE);
    for (ch = 0; ch < channels; ch++) {
        DitherState *state = &c->state[ch];
        state->mute = c->mute_reset_threshold + 1;
        state->seed = av_lfg_get(&seed_gen);
        generate_dither_noise(c, state, FFMAX(32768, sample_rate / 2));
    }

    return c;

fail:
    ff_dither_free(&c);
    return NULL;
}
Esempio n. 26
0
static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt) {
    a->fmt   = fmt;
    a->bps   = av_get_bytes_per_sample(fmt);
    a->planar= av_sample_fmt_is_planar(fmt);
}
Esempio n. 27
0
AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms,
        enum AVSampleFormat sample_fmt, int size,
        uint64_t channel_layout, int planar)
{
    AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer));
    AVFilterBufferRef *ref = NULL;
    int i, sample_size, chans_nb, bufsize, per_channel_size, step_size = 0;
    char *buf;

    if (!samples || !(ref = av_mallocz(sizeof(AVFilterBufferRef))))
        goto fail;

    ref->buf                   = samples;
    ref->format                = sample_fmt;

    ref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps));
    if (!ref->audio)
        goto fail;

    ref->audio->channel_layout = channel_layout;
    ref->audio->size           = size;
    ref->audio->planar         = planar;

    /* make sure the buffer gets read permission or it's useless for output */
    ref->perms = perms | AV_PERM_READ;

    samples->refcount   = 1;
    samples->free       = ff_avfilter_default_free_buffer;

    sample_size = av_get_bytes_per_sample(sample_fmt);
    chans_nb = av_get_channel_layout_nb_channels(channel_layout);

    per_channel_size = size/chans_nb;
    ref->audio->nb_samples = per_channel_size/sample_size;

    /* Set the number of bytes to traverse to reach next sample of a particular channel:
     * For planar, this is simply the sample size.
     * For packed, this is the number of samples * sample_size.
     */
    for (i = 0; i < chans_nb; i++)
        samples->linesize[i] = planar > 0 ? per_channel_size : sample_size;
    memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->linesize[0]));

    /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
    bufsize = (size + 15)&~15;
    buf = av_malloc(bufsize);
    if (!buf)
        goto fail;

    /* For planar, set the start point of each channel's data within the buffer
     * For packed, set the start point of the entire buffer only
     */
    samples->data[0] = buf;
    if (buf && planar) {
        for (i = 1; i < chans_nb; i++) {
            step_size += per_channel_size;
            samples->data[i] = buf + step_size;
        }
    } else {
        for (i = 1; i < chans_nb; i++)
            samples->data[i] = buf;
    }

    memset(&samples->data[chans_nb], 0, (8-chans_nb) * sizeof(samples->data[0]));

    memcpy(ref->data,     samples->data,     sizeof(ref->data));
    memcpy(ref->linesize, samples->linesize, sizeof(ref->linesize));

    return ref;

fail:
    if (ref)
        av_free(ref->audio);
    av_free(ref);
    av_free(samples);
    return NULL;
}
Esempio n. 28
0
static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
{
    AVCodec *codec;
    AVCodecContext *context;
    hb_audio_t *audio = w->audio;

    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
    w->private_data       = pv;
    pv->job               = job;
    pv->list              = hb_list_init();

    // channel count, layout and matrix encoding
    int matrix_encoding;
    uint64_t channel_layout   = hb_ff_mixdown_xlat(audio->config.out.mixdown,
                                                   &matrix_encoding);
    pv->out_discrete_channels =
        hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

    // default settings and options
    AVDictionary *av_opts          = NULL;
    const char *codec_name         = NULL;
    enum AVCodecID codec_id        = AV_CODEC_ID_NONE;
    enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
    int bits_per_raw_sample        = 0;
    int profile                    = FF_PROFILE_UNKNOWN;

    // override with encoder-specific values
    switch (audio->config.out.codec)
    {
        case HB_ACODEC_AC3:
            codec_id = AV_CODEC_ID_AC3;
            if (matrix_encoding != AV_MATRIX_ENCODING_NONE)
                av_dict_set(&av_opts, "dsur_mode", "on", 0);
            break;

        case HB_ACODEC_FDK_AAC:
        case HB_ACODEC_FDK_HAAC:
            codec_name          = "libfdk_aac";
            sample_fmt          = AV_SAMPLE_FMT_S16;
            bits_per_raw_sample = 16;
            switch (audio->config.out.codec)
            {
                case HB_ACODEC_FDK_HAAC:
                    profile = FF_PROFILE_AAC_HE;
                    break;
                default:
                    profile = FF_PROFILE_AAC_LOW;
                    break;
            }
            // Libav's libfdk-aac wrapper expects back channels for 5.1
            // audio, and will error out unless we translate the layout
            if (channel_layout == AV_CH_LAYOUT_5POINT1)
                channel_layout  = AV_CH_LAYOUT_5POINT1_BACK;
            break;

        case HB_ACODEC_FFAAC:
            codec_name = "aac";
            av_dict_set(&av_opts, "stereo_mode", "ms_off", 0);
            break;

        case HB_ACODEC_FFFLAC:
        case HB_ACODEC_FFFLAC24:
            codec_id = AV_CODEC_ID_FLAC;
            switch (audio->config.out.codec)
            {
                case HB_ACODEC_FFFLAC24:
                    sample_fmt          = AV_SAMPLE_FMT_S32;
                    bits_per_raw_sample = 24;
                    break;
                default:
                    sample_fmt          = AV_SAMPLE_FMT_S16;
                    bits_per_raw_sample = 16;
                    break;
            }
            break;

        default:
            hb_error("encavcodecaInit: unsupported codec (0x%x)",
                     audio->config.out.codec);
            return 1;
    }
    if (codec_name != NULL)
    {
        codec = avcodec_find_encoder_by_name(codec_name);
        if (codec == NULL)
        {
            hb_error("encavcodecaInit: avcodec_find_encoder_by_name(%s) failed",
                     codec_name);
            return 1;
        }
    }
    else
    {
        codec = avcodec_find_encoder(codec_id);
        if (codec == NULL)
        {
            hb_error("encavcodecaInit: avcodec_find_encoder(%d) failed",
                     codec_id);
            return 1;
        }
    }
    // allocate the context and apply the settings
    context                      = avcodec_alloc_context3(codec);
    hb_ff_set_sample_fmt(context, codec, sample_fmt);
    context->bits_per_raw_sample = bits_per_raw_sample;
    context->profile             = profile;
    context->channel_layout      = channel_layout;
    context->channels            = pv->out_discrete_channels;
    context->sample_rate         = audio->config.out.samplerate;

    if (audio->config.out.bitrate > 0)
    {
        context->bit_rate = audio->config.out.bitrate * 1000;
    }
    else if (audio->config.out.quality >= 0)
    {
        context->global_quality = audio->config.out.quality * FF_QP2LAMBDA;
        context->flags |= CODEC_FLAG_QSCALE;
    }

    if (audio->config.out.compression_level >= 0)
    {
        context->compression_level = audio->config.out.compression_level;
    }

    // For some codecs, libav requires the following flag to be set
    // so that it fills extradata with global header information.
    // If this flag is not set, it inserts the data into each
    // packet instead.
    context->flags |= CODEC_FLAG_GLOBAL_HEADER;

    if (hb_avcodec_open(context, codec, &av_opts, 0))
    {
        hb_error("encavcodecaInit: hb_avcodec_open() failed");
        return 1;
    }
    // avcodec_open populates the opts dictionary with the
    // things it didn't recognize.
    AVDictionaryEntry *t = NULL;
    while ((t = av_dict_get(av_opts, "", t, AV_DICT_IGNORE_SUFFIX)))
    {
        hb_log("encavcodecaInit: Unknown avcodec option %s", t->key);
    }
    av_dict_free(&av_opts);

    pv->context           = context;
    audio->config.out.samples_per_frame =
    pv->samples_per_frame = context->frame_size;
    pv->input_samples     = context->frame_size * context->channels;
    pv->input_buf         = malloc(pv->input_samples * sizeof(float));
    pv->max_output_bytes  = (pv->input_samples *
                             av_get_bytes_per_sample(context->sample_fmt));

    // sample_fmt conversion
    if (context->sample_fmt != AV_SAMPLE_FMT_FLT)
    {
        pv->output_buf = malloc(pv->max_output_bytes);
        pv->avresample = avresample_alloc_context();
        if (pv->avresample == NULL)
        {
            hb_error("encavcodecaInit: avresample_alloc_context() failed");
            return 1;
        }
        av_opt_set_int(pv->avresample, "in_sample_fmt",
                       AV_SAMPLE_FMT_FLT, 0);
        av_opt_set_int(pv->avresample, "out_sample_fmt",
                       context->sample_fmt, 0);
        av_opt_set_int(pv->avresample, "in_channel_layout",
                       context->channel_layout, 0);
        av_opt_set_int(pv->avresample, "out_channel_layout",
                       context->channel_layout, 0);
        if (hb_audio_dither_is_supported(audio->config.out.codec))
        {
            // dithering needs the sample rate
            av_opt_set_int(pv->avresample, "in_sample_rate",
                           context->sample_rate, 0);
            av_opt_set_int(pv->avresample, "out_sample_rate",
                           context->sample_rate, 0);
            av_opt_set_int(pv->avresample, "dither_method",
                           audio->config.out.dither_method, 0);
        }
        if (avresample_open(pv->avresample))
        {
            hb_error("encavcodecaInit: avresample_open() failed");
            avresample_free(&pv->avresample);
            return 1;
        }
    }
    else
    {
        pv->avresample = NULL;
        pv->output_buf = pv->input_buf;
    }

    if (context->extradata != NULL)
    {
        memcpy(w->config->extradata.bytes, context->extradata,
               context->extradata_size);
        w->config->extradata.length = context->extradata_size;
    }

    return 0;
}
Esempio n. 29
0
int
scan_metadata_ffmpeg(char *file, struct media_file_info *mfi)
{
  AVFormatContext *ctx;
  const struct metadata_map *extra_md_map;
  enum CodecID codec_id;
  enum CodecID video_codec_id;
  enum CodecID audio_codec_id;
  AVStream *video_stream;
  AVStream *audio_stream;
  int mdcount;
  int i;
  int ret;

  ctx = NULL;

#if LIBAVFORMAT_VERSION_MAJOR >= 53 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 3)
  ret = avformat_open_input(&ctx, file, NULL, NULL);
#else
  ret = av_open_input_file(&ctx, file, NULL, 0, NULL);
#endif
  if (ret != 0)
    {
      DPRINTF(E_WARN, L_SCAN, "Cannot open media file '%s': %s\n", file, strerror(AVUNERROR(ret)));

      return -1;
    }

  ret = av_find_stream_info(ctx);
  if (ret < 0)
    {
      DPRINTF(E_WARN, L_SCAN, "Cannot get stream info: %s\n", strerror(AVUNERROR(ret)));

      av_close_input_file(ctx);
      return -1;
    }

#if 0
  /* Dump input format as determined by ffmpeg */
# if LIBAVFORMAT_VERSION_MAJOR >= 52 || (LIBAVFORMAT_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 101)
  av_dump_format(ctx, 0, file, 0);
# else
  dump_format(ctx, 0, file, FALSE);
# endif
#endif

  DPRINTF(E_DBG, L_SCAN, "File has %d streams\n", ctx->nb_streams);

  /* Extract codec IDs, check for video */
  video_codec_id = CODEC_ID_NONE;
  video_stream = NULL;

  audio_codec_id = CODEC_ID_NONE;
  audio_stream = NULL;

  for (i = 0; i < ctx->nb_streams; i++)
    {
      switch (ctx->streams[i]->codec->codec_type)
	{
#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64)
	  case AVMEDIA_TYPE_VIDEO:
#else
	  case CODEC_TYPE_VIDEO:
#endif
	    if (!video_stream)
	      {
		DPRINTF(E_DBG, L_SCAN, "File has video (stream %d)\n", i);

		mfi->has_video = 1;
		video_stream = ctx->streams[i];
		video_codec_id = video_stream->codec->codec_id;
	      }
	    break;

#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64)
	  case AVMEDIA_TYPE_AUDIO:
#else
	  case CODEC_TYPE_AUDIO:
#endif
	    if (!audio_stream)
	      {
		audio_stream = ctx->streams[i];
		audio_codec_id = audio_stream->codec->codec_id;
	      } 
	    break;

	  default:
	    break;
	}
    }

  if (audio_codec_id == CODEC_ID_NONE)
    {
      DPRINTF(E_DBG, L_SCAN, "File has no audio streams, discarding\n");

      av_close_input_file(ctx);
      return -1;
    }

  /* Common media information */
  if (ctx->duration > 0)
    mfi->song_length = ctx->duration / (AV_TIME_BASE / 1000); /* ms */

  if (ctx->bit_rate > 0)
    mfi->bitrate = ctx->bit_rate / 1000;
  else if (ctx->duration > AV_TIME_BASE) /* guesstimate */
    mfi->bitrate = ((mfi->file_size * 8) / (ctx->duration / AV_TIME_BASE)) / 1000;

  DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate);

  /* Get some more information on the audio stream */
  if (audio_stream)
    {
      if (audio_stream->codec->sample_rate != 0)
	mfi->samplerate = audio_stream->codec->sample_rate;

      /* Try sample format first */
#if LIBAVUTIL_VERSION_MAJOR >= 51 || (LIBAVUTIL_VERSION_MAJOR == 51 && LIBAVUTIL_VERSION_MINOR >= 4)
      mfi->bits_per_sample = 8 * av_get_bytes_per_sample(audio_stream->codec->sample_fmt);
#elif LIBAVCODEC_VERSION_MAJOR >= 53
      mfi->bits_per_sample = av_get_bits_per_sample_fmt(audio_stream->codec->sample_fmt);
#else
      mfi->bits_per_sample = av_get_bits_per_sample_format(audio_stream->codec->sample_fmt);
#endif
      if (mfi->bits_per_sample == 0)
	{
	  /* Try codec */
	  mfi->bits_per_sample = av_get_bits_per_sample(audio_codec_id);
	}

      DPRINTF(E_DBG, L_SCAN, "samplerate %d, bps %d\n", mfi->samplerate, mfi->bits_per_sample);
    }

  /* Check codec */
  extra_md_map = NULL;
  codec_id = (mfi->has_video) ? video_codec_id : audio_codec_id;
  switch (codec_id)
    {
      case CODEC_ID_AAC:
	DPRINTF(E_DBG, L_SCAN, "AAC\n");
	mfi->type = strdup("m4a");
	mfi->codectype = strdup("mp4a");
	mfi->description = strdup("AAC audio file");
	break;

      case CODEC_ID_ALAC:
	DPRINTF(E_DBG, L_SCAN, "ALAC\n");
	mfi->type = strdup("m4a");
	mfi->codectype = strdup("alac");
	mfi->description = strdup("AAC audio file");
	break;

      case CODEC_ID_FLAC:
	DPRINTF(E_DBG, L_SCAN, "FLAC\n");
	mfi->type = strdup("flac");
	mfi->codectype = strdup("flac");
	mfi->description = strdup("FLAC audio file");

	extra_md_map = md_map_vorbis;
	break;

      case CODEC_ID_MUSEPACK7:
      case CODEC_ID_MUSEPACK8:
	DPRINTF(E_DBG, L_SCAN, "Musepack\n");
	mfi->type = strdup("mpc");
	mfi->codectype = strdup("mpc");
	mfi->description = strdup("Musepack audio file");
	break;

      case CODEC_ID_MPEG4: /* Video */
      case CODEC_ID_H264:
	DPRINTF(E_DBG, L_SCAN, "MPEG4 video\n");
	mfi->type = strdup("m4v");
	mfi->codectype = strdup("mp4v");
	mfi->description = strdup("MPEG-4 video file");

	extra_md_map = md_map_tv;
	break;

      case CODEC_ID_MP3:
	DPRINTF(E_DBG, L_SCAN, "MP3\n");
	mfi->type = strdup("mp3");
	mfi->codectype = strdup("mpeg");
	mfi->description = strdup("MPEG audio file");

	extra_md_map = md_map_id3;
	break;

      case CODEC_ID_VORBIS:
	DPRINTF(E_DBG, L_SCAN, "VORBIS\n");
	mfi->type = strdup("ogg");
	mfi->codectype = strdup("ogg");
	mfi->description = strdup("Ogg Vorbis audio file");

	extra_md_map = md_map_vorbis;
	break;

      case CODEC_ID_WMAVOICE:
	DPRINTF(E_DBG, L_SCAN, "WMA Voice\n");
	mfi->type = strdup("wma");
	mfi->codectype = strdup("wmav");
	mfi->description = strdup("WMA audio file");
	break;

      case CODEC_ID_WMAPRO:
	DPRINTF(E_DBG, L_SCAN, "WMA Pro\n");
	mfi->type = strdup("wmap");
	mfi->codectype = strdup("wma");
	mfi->description = strdup("WMA audio file");
	break;

      case CODEC_ID_WMALOSSLESS:
	DPRINTF(E_DBG, L_SCAN, "WMA Lossless\n");
	mfi->type = strdup("wma");
	mfi->codectype = strdup("wmal");
	mfi->description = strdup("WMA audio file");
	break;

      case CODEC_ID_WMAV1:
      case CODEC_ID_WMAV2:
	DPRINTF(E_DBG, L_SCAN, "WMA V1/V2\n");
	mfi->type = strdup("wma");
	mfi->codectype = strdup("wma");
	mfi->description = strdup("WMA audio file");
	break;

      case CODEC_ID_PCM_S16LE ... CODEC_ID_PCM_F64LE:
	if (strcmp(ctx->iformat->name, "aiff") == 0)
	  {
	    DPRINTF(E_DBG, L_SCAN, "AIFF\n");
	    mfi->type = strdup("aif");
	    mfi->codectype = strdup("aif");
	    mfi->description = strdup("AIFF audio file");
	    break;
	  }
	else if (strcmp(ctx->iformat->name, "wav") == 0)
	  {
	    DPRINTF(E_DBG, L_SCAN, "WAV\n");
	    mfi->type = strdup("wav");
	    mfi->codectype = strdup("wav");
	    mfi->description = strdup("WAV audio file");
	    break;
	  }
	/* WARNING: will fallthrough to default case, don't move */
	/* FALLTHROUGH */

      default:
	DPRINTF(E_DBG, L_SCAN, "Unknown codec 0x%x (video: %s), format %s (%s)\n",
		codec_id, (mfi->has_video) ? "yes" : "no", ctx->iformat->name, ctx->iformat->long_name);
	mfi->type = strdup("unkn");
	mfi->codectype = strdup("unkn");
	if (mfi->has_video)
	  {
	    mfi->description = strdup("Unknown video file format");
	    extra_md_map = md_map_tv;
	  }
	else
	  mfi->description = strdup("Unknown audio file format");
	break;
    }

  mdcount = 0;

  if ((!ctx->metadata) && (!audio_stream->metadata)
      && (video_stream && !video_stream->metadata))
    {
      DPRINTF(E_WARN, L_SCAN, "ffmpeg reports no metadata\n");

      goto skip_extract;
    }

  if (extra_md_map)
    {
      ret = extract_metadata(mfi, ctx, audio_stream, video_stream, extra_md_map);
      mdcount += ret;

      DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with extra md_map\n", ret);
    }

#if LIBAVFORMAT_VERSION_MAJOR < 53
  av_metadata_conv(ctx, NULL, ctx->iformat->metadata_conv);
#endif

  ret = extract_metadata(mfi, ctx, audio_stream, video_stream, md_map_generic);
  mdcount += ret;

  DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with generic md_map, %d tags total\n", ret, mdcount);

  /* fix up TV metadata */
  if (mfi->media_kind == 10)
    {
      /* I have no idea why this is, but iTunes reports a media kind of 64 for stik==10 (?!) */
      mfi->media_kind = 64;
    }
  /* Unspecified video files are "Movies", media_kind 2 */
  else if (mfi->has_video == 1)
    {
      mfi->media_kind = 2;
    }

 skip_extract:
  if (mdcount == 0)
    {
      /* ffmpeg doesn't support FLAC nor Musepack metadata,
       * and is buggy for some WMA variants, so fall back to the
       * legacy format-specific parsers until it gets fixed */
      if ((codec_id == CODEC_ID_WMAPRO)
	  || (codec_id == CODEC_ID_WMAVOICE)
	  || (codec_id == CODEC_ID_WMALOSSLESS))
	{
	  DPRINTF(E_WARN, L_SCAN, "Falling back to legacy WMA scanner\n");

	  av_close_input_file(ctx);
	  return (scan_get_wmainfo(file, mfi) ? 0 : -1);
	}
#ifdef FLAC
      else if (codec_id == CODEC_ID_FLAC)
	{
	  DPRINTF(E_WARN, L_SCAN, "Falling back to legacy FLAC scanner\n");

	  av_close_input_file(ctx);
	  return (scan_get_flacinfo(file, mfi) ? 0 : -1);
	}
#endif /* FLAC */
#ifdef MUSEPACK
      else if ((codec_id == CODEC_ID_MUSEPACK7)
	       || (codec_id == CODEC_ID_MUSEPACK8))
	{
	  DPRINTF(E_WARN, L_SCAN, "Falling back to legacy Musepack scanner\n");

	  av_close_input_file(ctx);
	  return (scan_get_mpcinfo(file, mfi) ? 0 : -1);
	}
#endif /* MUSEPACK */
      else
	DPRINTF(E_WARN, L_SCAN, "Could not extract any metadata\n");
    }

  /* Just in case there's no title set ... */
  if (mfi->title == NULL)
    mfi->title = strdup(mfi->fname);

  /* All done */
  av_close_input_file(ctx);

  return 0;
}
Esempio n. 30
0
void Movie::EncodeAudio(bool last)
{
    AVStream *astream = av->fmt_ctx->streams[av->audio_stream_idx];
    AVCodecContext *acodec = astream->codec;
    
    
    av_fifo_generic_write(av->audio_fifo, &audiobuf[0], audiobuf.size(), NULL);
    
    // bps: bytes per sample
    int channels = acodec->channels;
    int read_bps = 2;
    int write_bps = av_get_bytes_per_sample(acodec->sample_fmt);
    
    int max_read = acodec->frame_size * read_bps * channels;
    int min_read = last ? read_bps * channels : max_read;
    while (av_fifo_size(av->audio_fifo) >= min_read)
    {
        int read_bytes = MIN(av_fifo_size(av->audio_fifo), max_read);
        av_fifo_generic_read(av->audio_fifo, av->audio_data, read_bytes, NULL);
        
        // convert
        int read_samples = read_bytes / (read_bps * channels);
        int write_samples = read_samples;
        if (read_samples < acodec->frame_size)
        {
            // shrink or pad audio frame
            if (acodec->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)
                acodec->frame_size = write_samples;
            else
                write_samples = acodec->frame_size;
        }

        convert_audio(read_samples, acodec->channels, -1,
                      AV_SAMPLE_FMT_S16, av->audio_data,
                      write_samples, acodec->channels, write_samples * write_bps,
                      acodec->sample_fmt, av->audio_data_conv);
                      
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
        avcodec_get_frame_defaults(av->audio_frame);
#else
        av_frame_unref(av->audio_frame);
#endif
        av->audio_frame->nb_samples = write_samples;
        av->audio_frame->pts = av_rescale_q(av->audio_counter,
                                            (AVRational){1, acodec->sample_rate},
                                            acodec->time_base);
        av->audio_counter += write_samples;
        int asize = avcodec_fill_audio_frame(av->audio_frame, acodec->channels,
                                             acodec->sample_fmt,
                                             av->audio_data_conv,
                                             write_samples * write_bps * channels, 1);
        if (asize >= 0)
        {
            AVPacket pkt;
            memset(&pkt, 0, sizeof(AVPacket));
            av_init_packet(&pkt);
            
            int got_pkt = 0;
            if (0 == avcodec_encode_audio2(acodec, &pkt, av->audio_frame, &got_pkt)
                && got_pkt)
            {
                if (pkt.pts != AV_NOPTS_VALUE && pkt.pts < pkt.dts)
                    pkt.pts = pkt.dts;
                if (pkt.pts != AV_NOPTS_VALUE)
                    pkt.pts = av_rescale_q(pkt.pts, acodec->time_base, astream->time_base);
                if (pkt.dts != AV_NOPTS_VALUE)
                    pkt.dts = av_rescale_q(pkt.dts, acodec->time_base, astream->time_base);
                pkt.duration = av_rescale_q(pkt.duration, acodec->time_base, astream->time_base);
                pkt.stream_index = astream->index;
                av_interleaved_write_frame(av->fmt_ctx, &pkt);
                av_free_packet(&pkt);
            }
        }
    }
    if (last)
    {
        bool done = false;
        while (!done)
        {
            AVPacket pkt;
            memset(&pkt, 0, sizeof(AVPacket));
            av_init_packet(&pkt);
            
            int got_pkt = 0;
            if (0 == avcodec_encode_audio2(acodec, &pkt, NULL, &got_pkt)
                && got_pkt)
            {
                if (pkt.pts != AV_NOPTS_VALUE && pkt.pts < pkt.dts)
                    pkt.pts = pkt.dts;
                if (pkt.pts != AV_NOPTS_VALUE)
                    pkt.pts = av_rescale_q(pkt.pts, acodec->time_base, astream->time_base);
                if (pkt.dts != AV_NOPTS_VALUE)
                    pkt.dts = av_rescale_q(pkt.dts, acodec->time_base, astream->time_base);
                pkt.duration = av_rescale_q(pkt.duration, acodec->time_base, astream->time_base);
                pkt.stream_index = astream->index;
                av_interleaved_write_frame(av->fmt_ctx, &pkt);
                av_free_packet(&pkt);
            }
            else
            {
                done = true;
            }
        }
        
    }
    
}