Added ChargeAudio and subsequently a half baked audio support
Audio is almost ready(thank you miniaudio), there is a drift that needs to be solved and then we are golden.
This commit is contained in:
@@ -36,6 +36,7 @@ target_link_libraries(
|
|||||||
PRIVATE Corrade::Main
|
PRIVATE Corrade::Main
|
||||||
Magnum::GL
|
Magnum::GL
|
||||||
Magnum::Magnum
|
Magnum::Magnum
|
||||||
|
ChargeAudio::ChargeAudio
|
||||||
${AVFORMAT_LIBRARIES}
|
${AVFORMAT_LIBRARIES}
|
||||||
${AVCODEC_LIBRARIES}
|
${AVCODEC_LIBRARIES}
|
||||||
${AVUTIL_LIBRARIES}
|
${AVUTIL_LIBRARIES}
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
#ifndef CHARGE_VIDEO_BASE_H
|
#ifndef CHARGE_VIDEO_BASE_H
|
||||||
#define CHARGE_VIDEO_BASE_H
|
#define CHARGE_VIDEO_BASE_H
|
||||||
|
|
||||||
#include <Corrade/Containers/Array.h>
|
|
||||||
#include <Magnum/GL/Texture.h>
|
|
||||||
#include <Magnum/Image.h>
|
|
||||||
#include <Magnum/ImageView.h>
|
|
||||||
#include <Magnum/Magnum.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Magnum/GL/Texture.h>
|
||||||
|
#include <Magnum/Image.h>
|
||||||
|
#include <Magnum/ImageView.h>
|
||||||
|
#include <Magnum/Magnum.h>
|
||||||
|
#include <Magnum/Timeline.h>
|
||||||
|
|
||||||
|
#include <Charge/ChargeAudio.hpp>
|
||||||
|
|
||||||
namespace ChargeVideo {
|
namespace ChargeVideo {
|
||||||
namespace _ffmpeg {
|
namespace _ffmpeg {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -60,8 +63,8 @@ private:
|
|||||||
|
|
||||||
class Video {
|
class Video {
|
||||||
public:
|
public:
|
||||||
Video(std::string path, bool ShouldVideoLoop = true,
|
Video(std::string path, ChargeAudio::Engine *audioEngine = nullptr,
|
||||||
float BufferSizeInSeconds = 1.0f);
|
bool ShouldVideoLoop = true, float BufferSizeInSeconds = 1.0f);
|
||||||
~Video();
|
~Video();
|
||||||
|
|
||||||
// Manual Control
|
// Manual Control
|
||||||
@@ -99,6 +102,13 @@ private:
|
|||||||
uint32_t currentFrameNumber = 0;
|
uint32_t currentFrameNumber = 0;
|
||||||
float timeSink = 0.0f, frameTime = 0.0f;
|
float timeSink = 0.0f, frameTime = 0.0f;
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
ChargeAudio::Engine *audioEngine;
|
||||||
|
ChargeAudio::SoundContainer bufferedAudio;
|
||||||
|
|
||||||
|
_ffmpeg::AVChannelLayout outLayout;
|
||||||
|
_ffmpeg::AVSampleFormat sampleFormat = _ffmpeg::AV_SAMPLE_FMT_FLT;
|
||||||
|
|
||||||
// Buffering
|
// Buffering
|
||||||
std::queue<Image2D> frameBuffer;
|
std::queue<Image2D> frameBuffer;
|
||||||
uint32_t bufferMaxFrames = 0;
|
uint32_t bufferMaxFrames = 0;
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
|
#include <Corrade/Containers/GrowableArray.h>
|
||||||
|
|
||||||
#include "ChargeVideo.hpp"
|
#include "ChargeVideo.hpp"
|
||||||
|
|
||||||
|
#include <Charge/ChargeAudio.hpp>
|
||||||
|
#include <Corrade/Utility/Debug.h>
|
||||||
#include <Corrade/Utility/Utility.h>
|
#include <Corrade/Utility/Utility.h>
|
||||||
|
|
||||||
#include <Magnum/GL/TextureFormat.h>
|
#include <Magnum/GL/TextureFormat.h>
|
||||||
#include <Magnum/Math/Functions.h>
|
#include <Magnum/Math/Functions.h>
|
||||||
#include <Magnum/PixelFormat.h>
|
#include <Magnum/PixelFormat.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
|
#include <libavutil/samplefmt.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
|
||||||
using namespace ChargeVideo;
|
using namespace ChargeVideo;
|
||||||
using namespace _ffmpeg;
|
using namespace _ffmpeg;
|
||||||
@@ -13,9 +20,10 @@ using namespace _ffmpeg;
|
|||||||
|
|
||||||
// ================== Video Construct/Destruct ==================
|
// ================== Video Construct/Destruct ==================
|
||||||
// ShouldVideoLoop default is true
|
// ShouldVideoLoop default is true
|
||||||
Video::Video(std::string path, bool ShouldVideoLoop, float BufferSizeInSeconds)
|
Video::Video(std::string path, ChargeAudio::Engine *engine,
|
||||||
|
bool ShouldVideoLoop, float BufferSizeInSeconds)
|
||||||
: BufferLenghtInSeconds(BufferSizeInSeconds),
|
: BufferLenghtInSeconds(BufferSizeInSeconds),
|
||||||
isVideoLooping(ShouldVideoLoop) {
|
isVideoLooping(ShouldVideoLoop), audioEngine(engine) {
|
||||||
// Context to hold our data
|
// Context to hold our data
|
||||||
ctx = avformat_alloc_context();
|
ctx = avformat_alloc_context();
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@@ -63,7 +71,7 @@ Video::Video(std::string path, bool ShouldVideoLoop, float BufferSizeInSeconds)
|
|||||||
NULL); // open2 is such a stupid name
|
NULL); // open2 is such a stupid name
|
||||||
|
|
||||||
// Some videos do not have audio streams
|
// Some videos do not have audio streams
|
||||||
if (audioStreamNum != -1) {
|
if (audioStreamNum != -1 && audioEngine) {
|
||||||
aCodec = avcodec_find_decoder(audioStream->codecpar->codec_id);
|
aCodec = avcodec_find_decoder(audioStream->codecpar->codec_id);
|
||||||
aCodecCtx = avcodec_alloc_context3(aCodec);
|
aCodecCtx = avcodec_alloc_context3(aCodec);
|
||||||
avcodec_parameters_to_context(aCodecCtx, audioStream->codecpar);
|
avcodec_parameters_to_context(aCodecCtx, audioStream->codecpar);
|
||||||
@@ -72,11 +80,18 @@ Video::Video(std::string path, bool ShouldVideoLoop, float BufferSizeInSeconds)
|
|||||||
|
|
||||||
// Hoo boy I love bunch of different ways to do the same thing!!!!!!
|
// Hoo boy I love bunch of different ways to do the same thing!!!!!!
|
||||||
// Now we have to deal with all of the ways to do that thing!!!!!
|
// Now we have to deal with all of the ways to do that thing!!!!!
|
||||||
AVChannelLayout outLayout = AV_CHANNEL_LAYOUT_STEREO;
|
if (audioEngine->GetChannelCount() == 2) {
|
||||||
swr_alloc_set_opts2(&swrCtx, &outLayout, AV_SAMPLE_FMT_S16, 44100,
|
outLayout = AV_CHANNEL_LAYOUT_STEREO;
|
||||||
&aCodecCtx->ch_layout, aCodecCtx->sample_fmt,
|
} else {
|
||||||
aCodecCtx->sample_rate, 0, NULL);
|
outLayout = AV_CHANNEL_LAYOUT_MONO;
|
||||||
|
}
|
||||||
|
swr_alloc_set_opts2(&swrCtx, &outLayout, sampleFormat,
|
||||||
|
audioEngine->GetSampleRate(), &aCodecCtx->ch_layout,
|
||||||
|
aCodecCtx->sample_fmt, aCodecCtx->sample_rate, 0, NULL);
|
||||||
swr_init(swrCtx);
|
swr_init(swrCtx);
|
||||||
|
|
||||||
|
// Creating buffered audio
|
||||||
|
bufferedAudio = audioEngine->CreateSound(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timing stuff
|
// Timing stuff
|
||||||
@@ -155,6 +170,8 @@ void Video::continueVideo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadTexture(frameBuffer.front());
|
loadTexture(frameBuffer.front());
|
||||||
|
if (bufferedAudio->GetState() == ChargeAudio::Sound::SoundState::Idle)
|
||||||
|
bufferedAudio->Play();
|
||||||
frameBuffer.pop();
|
frameBuffer.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,20 +184,22 @@ Containers::Array<char> Video::loadNextFrame() {
|
|||||||
|
|
||||||
// A hard stop if we are out of frames to read
|
// A hard stop if we are out of frames to read
|
||||||
while (av_read_frame(ctx, packet) >= 0) {
|
while (av_read_frame(ctx, packet) >= 0) {
|
||||||
if (static_cast<int8_t>(packet->stream_index) == audioStreamNum) {
|
if (audioEngine &&
|
||||||
|
static_cast<int8_t>(packet->stream_index) == audioStreamNum) {
|
||||||
avcodec_send_packet(aCodecCtx, packet);
|
avcodec_send_packet(aCodecCtx, packet);
|
||||||
avcodec_receive_frame(aCodecCtx, audioFrame);
|
avcodec_receive_frame(aCodecCtx, audioFrame);
|
||||||
if (audioFrame->format != -1) {
|
if (audioFrame->format != -1 && audioEngine) {
|
||||||
convertedAudioFrame->format = AV_SAMPLE_FMT_S16;
|
convertedAudioFrame->format = sampleFormat;
|
||||||
|
convertedAudioFrame->sample_rate = audioEngine->GetSampleRate();
|
||||||
|
convertedAudioFrame->ch_layout = outLayout;
|
||||||
convertedAudioFrame->nb_samples =
|
convertedAudioFrame->nb_samples =
|
||||||
swr_get_out_samples(swrCtx, audioFrame->nb_samples);
|
swr_get_out_samples(swrCtx, audioFrame->nb_samples);
|
||||||
convertedAudioFrame->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
|
av_frame_get_buffer(convertedAudioFrame, 0);
|
||||||
av_frame_get_buffer(convertedAudioFrame,
|
|
||||||
2); // since it is LRLRLRLRLRLRLR
|
|
||||||
|
|
||||||
swr_convert(swrCtx, convertedAudioFrame->data,
|
swr_convert_frame(swrCtx, convertedAudioFrame, audioFrame);
|
||||||
convertedAudioFrame->nb_samples, audioFrame->data,
|
|
||||||
audioFrame->nb_samples);
|
bufferedAudio->WriteToRingBuffer(convertedAudioFrame->data[0],
|
||||||
|
convertedAudioFrame->linesize[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user