mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Provide a new method AuCtx::AuCreateCodecContextFromSource()
This method can automatically read audio information from file (as channels, sample rate etc) via ffmpeg, and create accurate ffmpeg's codec context. Especially used for unknown audio format but supported by ffmpeg.
This commit is contained in:
parent
73d8786078
commit
c6a1b0e743
3 changed files with 89 additions and 2 deletions
|
@ -326,6 +326,11 @@ int sceMp3Init(u32 mp3) {
|
|||
|
||||
INFO_LOG(ME, "sceMp3Init(): channels=%i, samplerate=%iHz, bitrate=%ikbps", ctx->Channels, ctx->SamplingRate, ctx->BitRate);
|
||||
|
||||
// Read information from source via ffmpeg and re-create codec context
|
||||
// This is an automatic method without knowledge in audio file format
|
||||
// ctx->AuCreateCodecContextFromSource();
|
||||
// INFO_LOG(ME, "sceMp3Init() ffmpeg: channels=%i, samplerate=%iHz, bitrate=%ikbps", ctx->Channels, ctx->SamplingRate, ctx->BitRate);
|
||||
|
||||
// for mp3, if required freq is 48000, reset resampling Frequency to 48000 seems get better sound quality (e.g. Miku Custom BGM)
|
||||
if (ctx->freq == 48000){
|
||||
ctx->decoder->setResampleFrequency(ctx->freq);
|
||||
|
|
|
@ -458,4 +458,86 @@ int AuCtx::AuGetVersion(){
|
|||
|
||||
int AuCtx::AuGetFrameNum(){
|
||||
return FrameNum;
|
||||
}
|
||||
}
|
||||
|
||||
static int _Readbuffer(void *opaque, uint8_t *buf, int buf_size) {
|
||||
auto ctx = (AuCtx *)opaque;
|
||||
int toread = std::min((int)ctx->AuBufSize, buf_size);
|
||||
memcpy(buf, Memory::GetPointer(ctx->AuBuf), toread);
|
||||
return toread;
|
||||
}
|
||||
|
||||
static void closeAvioCtxandFormatCtx(AVIOContext* pAVIOCtx, AVFormatContext* pFormatCtx){
|
||||
if (pAVIOCtx && pAVIOCtx->buffer)
|
||||
av_free(pAVIOCtx->buffer);
|
||||
if (pAVIOCtx)
|
||||
av_free(pAVIOCtx);
|
||||
if (pFormatCtx)
|
||||
avformat_close_input(&pFormatCtx);
|
||||
}
|
||||
|
||||
// you need at least have initialized AuBuf, AuBufSize and decoder
|
||||
bool AuCtx::AuCreateCodecContextFromSource(){
|
||||
u8* tempbuf = (u8*)av_malloc(AuBufSize);
|
||||
|
||||
auto pFormatCtx = avformat_alloc_context();
|
||||
auto pAVIOCtx = avio_alloc_context(tempbuf, AuBufSize, 0, (void*)this, _Readbuffer, NULL, NULL);
|
||||
pFormatCtx->pb = pAVIOCtx;
|
||||
|
||||
int ret;
|
||||
// Load audio buffer
|
||||
if ((ret = avformat_open_input((AVFormatContext**)&pFormatCtx, NULL, NULL, NULL)) != 0) {
|
||||
ERROR_LOG(ME, "avformat_open_input: Cannot open input %d", ret);
|
||||
closeAvioCtxandFormatCtx(pAVIOCtx,pFormatCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ret = avformat_find_stream_info(pFormatCtx, NULL)) < 0) {
|
||||
ERROR_LOG(ME, "avformat_find_stream_info: Cannot find stream information %d", ret);
|
||||
closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx);
|
||||
return false;
|
||||
}
|
||||
// reset decoder context
|
||||
if (decoder->codecCtx_){
|
||||
avcodec_close(decoder->codecCtx_);
|
||||
av_free(decoder->codecCtx_);
|
||||
}
|
||||
decoder->codecCtx_ = pFormatCtx->streams[ret]->codec;
|
||||
|
||||
if (decoder->codec_){
|
||||
decoder->codec_ = 0;
|
||||
}
|
||||
// select the audio stream
|
||||
ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &decoder->codec_, 0);
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_DECODER_NOT_FOUND) {
|
||||
ERROR_LOG(HLE, "av_find_best_stream: No appropriate decoder found");
|
||||
}
|
||||
else {
|
||||
ERROR_LOG(HLE, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret);
|
||||
}
|
||||
closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
// close and free AVIO and AVFormat
|
||||
// closeAvioCtxandFormatCtx(pAVIOCtx, pFormatCtx);
|
||||
|
||||
// open codec
|
||||
if ((ret = avcodec_open2(decoder->codecCtx_, decoder->codec_, NULL)) < 0) {
|
||||
avcodec_close(decoder->codecCtx_);
|
||||
av_free(decoder->codecCtx_);
|
||||
decoder->codecCtx_ = 0;
|
||||
decoder->codec_ = 0;
|
||||
ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
// set audio informations
|
||||
SamplingRate = decoder->codecCtx_->sample_rate;
|
||||
Channels = decoder->codecCtx_->channels;
|
||||
BitRate = decoder->codecCtx_->bit_rate/1000;
|
||||
freq = SamplingRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ public:
|
|||
int srcPos; // bytes consumed in source during the last decoding
|
||||
int wanted_resample_freq; // wanted resampling rate/frequency
|
||||
|
||||
private:
|
||||
#ifdef USE_FFMPEG
|
||||
AVFrame *frame_;
|
||||
AVCodec *codec_;
|
||||
|
@ -178,6 +177,7 @@ public:
|
|||
u32 AuResetPlayPositionByFrame(int position);
|
||||
int AuGetVersion();
|
||||
int AuGetFrameNum();
|
||||
bool AuCreateCodecContextFromSource();
|
||||
|
||||
void DoState(PointerWrap &p) {
|
||||
auto s = p.Section("AuContext", 0, 1);
|
||||
|
|
Loading…
Add table
Reference in a new issue