aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp')
-rw-r--r--externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp318
1 files changed, 0 insertions, 318 deletions
diff --git a/externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp b/externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp
deleted file mode 100644
index 97d212f369..0000000000
--- a/externals/oboe/samples/RhythmGame/src/main/cpp/audio/FFMpegExtractor.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <memory>
-#include <oboe/Definitions.h>
-#include "FFMpegExtractor.h"
-#include "utils/logging.h"
-
-constexpr int kInternalBufferSize = 1152; // Use MP3 block size. https://wiki.hydrogenaud.io/index.php?title=MP3
-
-int read(void *opaque, uint8_t *buf, int buf_size) {
-
- auto asset = (AAsset *) opaque;
- int bytesRead = AAsset_read(asset, buf, (size_t)buf_size);
- return bytesRead;
-}
-
-int64_t seek(void *opaque, int64_t offset, int whence){
-
- auto asset = (AAsset*)opaque;
-
- // See https://www.ffmpeg.org/doxygen/3.0/avio_8h.html#a427ff2a881637b47ee7d7f9e368be63f
- if (whence == AVSEEK_SIZE) return AAsset_getLength(asset);
- if (AAsset_seek(asset, offset, whence) == -1){
- return -1;
- } else {
- return 0;
- }
-}
-
-bool FFMpegExtractor::createAVIOContext(AAsset *asset, uint8_t *buffer, uint32_t bufferSize,
- AVIOContext **avioContext) {
-
- constexpr int isBufferWriteable = 0;
-
- *avioContext = avio_alloc_context(
- buffer, // internal buffer for FFmpeg to use
- bufferSize, // For optimal decoding speed this should be the protocol block size
- isBufferWriteable,
- asset, // Will be passed to our callback functions as a (void *)
- read, // Read callback function
- nullptr, // Write callback function (not used)
- seek); // Seek callback function
-
- if (*avioContext == nullptr){
- LOGE("Failed to create AVIO context");
- return false;
- } else {
- return true;
- }
-}
-
-bool
-FFMpegExtractor::createAVFormatContext(AVIOContext *avioContext, AVFormatContext **avFormatContext) {
-
- *avFormatContext = avformat_alloc_context();
- (*avFormatContext)->pb = avioContext;
-
- if (*avFormatContext == nullptr){
- LOGE("Failed to create AVFormatContext");
- return false;
- } else {
- return true;
- }
-}
-
-bool FFMpegExtractor::openAVFormatContext(AVFormatContext *avFormatContext) {
-
- int result = avformat_open_input(&avFormatContext,
- "", /* URL is left empty because we're providing our own I/O */
- nullptr /* AVInputFormat *fmt */,
- nullptr /* AVDictionary **options */
- );
-
- if (result == 0) {
- return true;
- } else {
- LOGE("Failed to open file. Error code %s", av_err2str(result));
- return false;
- }
-}
-
-bool FFMpegExtractor::getStreamInfo(AVFormatContext *avFormatContext) {
-
- int result = avformat_find_stream_info(avFormatContext, nullptr);
- if (result == 0 ){
- return true;
- } else {
- LOGE("Failed to find stream info. Error code %s", av_err2str(result));
- return false;
- }
-}
-
-AVStream *FFMpegExtractor::getBestAudioStream(AVFormatContext *avFormatContext) {
-
- int streamIndex = av_find_best_stream(avFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
-
- if (streamIndex < 0){
- LOGE("Could not find stream");
- return nullptr;
- } else {
- return avFormatContext->streams[streamIndex];
- }
-}
-
-int64_t FFMpegExtractor::decode(
- AAsset *asset,
- uint8_t *targetData,
- AudioProperties targetProperties) {
-
- LOGI("Decoder: FFMpeg");
-
- int returnValue = -1; // -1 indicates error
-
- // Create a buffer for FFmpeg to use for decoding (freed in the custom deleter below)
- auto buffer = reinterpret_cast<uint8_t*>(av_malloc(kInternalBufferSize));
-
- // Create an AVIOContext with a custom deleter
- std::unique_ptr<AVIOContext, void(*)(AVIOContext *)> ioContext {
- nullptr,
- [](AVIOContext *c) {
- av_free(c->buffer);
- avio_context_free(&c);
- }
- };
- {
- AVIOContext *tmp = nullptr;
- if (!createAVIOContext(asset, buffer, kInternalBufferSize, &tmp)){
- LOGE("Could not create an AVIOContext");
- return returnValue;
- }
- ioContext.reset(tmp);
- }
-
- // Create an AVFormatContext using the avformat_free_context as the deleter function
- std::unique_ptr<AVFormatContext, decltype(&avformat_free_context)> formatContext {
- nullptr,
- &avformat_free_context
- };
- {
- AVFormatContext *tmp;
- if (!createAVFormatContext(ioContext.get(), &tmp)) return returnValue;
- formatContext.reset(tmp);
- }
-
- if (!openAVFormatContext(formatContext.get())) return returnValue;
-
- if (!getStreamInfo(formatContext.get())) return returnValue;
-
- // Obtain the best audio stream to decode
- AVStream *stream = getBestAudioStream(formatContext.get());
- if (stream == nullptr || stream->codecpar == nullptr){
- LOGE("Could not find a suitable audio stream to decode");
- return returnValue;
- }
-
- printCodecParameters(stream->codecpar);
-
- // Find the codec to decode this stream
- AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id);
- if (!codec){
- LOGE("Could not find codec with ID: %d", stream->codecpar->codec_id);
- return returnValue;
- }
-
- // Create the codec context, specifying the deleter function
- std::unique_ptr<AVCodecContext, void(*)(AVCodecContext *)> codecContext {
- nullptr,
- [](AVCodecContext *c) { avcodec_free_context(&c); }
- };
- {
- AVCodecContext *tmp = avcodec_alloc_context3(codec);
- if (!tmp){
- LOGE("Failed to allocate codec context");
- return returnValue;
- }
- codecContext.reset(tmp);
- }
-
- // Copy the codec parameters into the context
- if (avcodec_parameters_to_context(codecContext.get(), stream->codecpar) < 0){
- LOGE("Failed to copy codec parameters to codec context");
- return returnValue;
- }
-
- // Open the codec
- if (avcodec_open2(codecContext.get(), codec, nullptr) < 0){
- LOGE("Could not open codec");
- return returnValue;
- }
-
- // prepare resampler
- int32_t outChannelLayout = (1 << targetProperties.channelCount) - 1;
- LOGD("Channel layout %d", outChannelLayout);
-
- SwrContext *swr = swr_alloc();
- av_opt_set_int(swr, "in_channel_count", stream->codecpar->channels, 0);
- av_opt_set_int(swr, "out_channel_count", targetProperties.channelCount, 0);
- av_opt_set_int(swr, "in_channel_layout", stream->codecpar->channel_layout, 0);
- av_opt_set_int(swr, "out_channel_layout", outChannelLayout, 0);
- av_opt_set_int(swr, "in_sample_rate", stream->codecpar->sample_rate, 0);
- av_opt_set_int(swr, "out_sample_rate", targetProperties.sampleRate, 0);
- av_opt_set_int(swr, "in_sample_fmt", stream->codecpar->format, 0);
- av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
- av_opt_set_int(swr, "force_resampling", 1, 0);
-
- // Check that resampler has been inited
- int result = swr_init(swr);
- if (result != 0){
- LOGE("swr_init failed. Error: %s", av_err2str(result));
- return returnValue;
- };
- if (!swr_is_initialized(swr)) {
- LOGE("swr_is_initialized is false\n");
- return returnValue;
- }
-
- // Prepare to read data
- int bytesWritten = 0;
- AVPacket avPacket; // Stores compressed audio data
- av_init_packet(&avPacket);
- AVFrame *decodedFrame = av_frame_alloc(); // Stores raw audio data
- int bytesPerSample = av_get_bytes_per_sample((AVSampleFormat)stream->codecpar->format);
-
- LOGD("Bytes per sample %d", bytesPerSample);
-
- LOGD("DECODE START");
-
- // While there is more data to read, read it into the avPacket
- while (av_read_frame(formatContext.get(), &avPacket) == 0){
-
- if (avPacket.stream_index == stream->index && avPacket.size > 0) {
-
- // Pass our compressed data into the codec
- result = avcodec_send_packet(codecContext.get(), &avPacket);
- if (result != 0) {
- LOGE("avcodec_send_packet error: %s", av_err2str(result));
- goto cleanup;
- }
-
- // Retrieve our raw data from the codec
- result = avcodec_receive_frame(codecContext.get(), decodedFrame);
- if (result == AVERROR(EAGAIN)) {
- // The codec needs more data before it can decode
- LOGI("avcodec_receive_frame returned EAGAIN");
- av_packet_unref(&avPacket);
- continue;
- } else if (result != 0) {
- LOGE("avcodec_receive_frame error: %s", av_err2str(result));
- goto cleanup;
- }
-
- // DO RESAMPLING
- auto dst_nb_samples = (int32_t) av_rescale_rnd(
- swr_get_delay(swr, decodedFrame->sample_rate) + decodedFrame->nb_samples,
- targetProperties.sampleRate,
- decodedFrame->sample_rate,
- AV_ROUND_UP);
-
- short *buffer1;
- av_samples_alloc(
- (uint8_t **) &buffer1,
- nullptr,
- targetProperties.channelCount,
- dst_nb_samples,
- AV_SAMPLE_FMT_FLT,
- 0);
- int frame_count = swr_convert(
- swr,
- (uint8_t **) &buffer1,
- dst_nb_samples,
- (const uint8_t **) decodedFrame->data,
- decodedFrame->nb_samples);
-
- int64_t bytesToWrite = frame_count * sizeof(float) * targetProperties.channelCount;
- memcpy(targetData + bytesWritten, buffer1, (size_t)bytesToWrite);
- bytesWritten += bytesToWrite;
- av_freep(&buffer1);
-
- av_packet_unref(&avPacket);
- }
- }
-
- av_frame_free(&decodedFrame);
- LOGD("DECODE END");
-
- returnValue = bytesWritten;
-
- cleanup:
- return returnValue;
-}
-
-void FFMpegExtractor::printCodecParameters(AVCodecParameters *params) {
-
- LOGD("Stream properties");
- LOGD("Channels: %d", params->channels);
- LOGD("Channel layout: %" PRId64, params->channel_layout);
- LOGD("Sample rate: %d", params->sample_rate);
- LOGD("Format: %s", av_get_sample_fmt_name((AVSampleFormat)params->format));
- LOGD("Frame size: %d", params->frame_size);
-}
-
-
-
-