diff --git a/src/ChargeVideo.hpp b/src/ChargeVideo.hpp index 89096a7..59f7a8d 100644 --- a/src/ChargeVideo.hpp +++ b/src/ChargeVideo.hpp @@ -104,6 +104,13 @@ private: Flags videoFlags; uint16_t ID = 0; + // Frames + _ffmpeg::AVFrame *frame = _ffmpeg::av_frame_alloc(), + *convertedFrame = _ffmpeg::av_frame_alloc(), + *audioFrame = _ffmpeg::av_frame_alloc(), + *convertedAudioFrame = _ffmpeg::av_frame_alloc(); + _ffmpeg::AVPacket *packet = _ffmpeg::av_packet_alloc(); + // Time specific uint32_t currentFrameNumber = 0; double timeBase = 0, clock = 0; @@ -132,8 +139,7 @@ private: std::pair> loadNextFrame(); inline void frameDebug(_ffmpeg::AVFrame *frame); inline void frameSetScaleSAR(_ffmpeg::AVFrame *frame); - inline void frameConvert(_ffmpeg::AVFrame *sourceFrame, - _ffmpeg::AVFrame *convertedFrame); + inline void frameConvert(); inline void frameFlip(_ffmpeg::AVFrame *frame); inline void restartVideo(); @@ -142,6 +148,8 @@ private: void loadTexture(Containers::Array data); void loadTexture(ImageView2D image); Image2D loadImage(Containers::Array data); + + void reinitSound(); }; inline Video::Flags operator|(Video::Flags x, Video::Flags y) { diff --git a/src/Video.cpp b/src/Video.cpp index 7bd7e6d..3f8929a 100644 --- a/src/Video.cpp +++ b/src/Video.cpp @@ -11,10 +11,16 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #include #include +#include #include #include @@ -40,6 +46,7 @@ Video::Video(std::string path, ChargeAudio::Engine *engine, Flags videoF, if (avformat_open_input(&ctx, path.c_str(), NULL, NULL) != 0) { Utility::Error{} << "Could not open file " << path.c_str(); + avformat_close_input(&ctx); avformat_free_context(ctx); return; } @@ -95,13 +102,15 @@ Video::Video(std::string path, ChargeAudio::Engine *engine, Flags videoF, outLayout = AV_CHANNEL_LAYOUT_MONO; } + // Resampling swr_alloc_set_opts2(&swrCtx, &outLayout, sampleFormat, audioEngine->GetSampleRate(), &aCodecCtx->ch_layout, aCodecCtx->sample_fmt, aCodecCtx->sample_rate, 0, NULL); swr_init(swrCtx); - // Creating buffered audio Sound = audioEngine->CreateSound(10); + + // Frame init } bufferMaxFrames = av_q2d(videoStream->avg_frame_rate) * bufferLenghtInSeconds; @@ -110,7 +119,16 @@ Video::Video(std::string path, ChargeAudio::Engine *engine, Flags videoF, Video::~Video() { sws_freeContext(swsCtx); - swr_free(&swrCtx); + if (audioStreamNum != -1) { + swr_free(&swrCtx); + av_frame_free(&audioFrame); + av_frame_free(&convertedAudioFrame); + } + av_frame_free(&frame); + av_frame_free(&convertedFrame); + av_packet_free(&packet); + + avformat_close_input(&ctx); avformat_free_context(ctx); avcodec_free_context(&vCodecCtx); avcodec_free_context(&aCodecCtx); @@ -124,6 +142,7 @@ void Video::Play() { return; } ID = Manager::hookVideo(std::bind(&Video::continueVideo, this)); + reinitSound(); if (audioStreamNum != -1) { Sound->Play(); } @@ -135,9 +154,7 @@ void Video::Pause() { return; } Manager::unhookVideo(ID); - if (audioStreamNum != -1) { - Sound->Pause(); - } + reinitSound(); ID = 0; videoState = State::Paused; } @@ -200,10 +217,10 @@ void Video::continueVideo() { // ======================== HELPERS ======================== std::pair> Video::loadNextFrame() { - AVFrame *frame = av_frame_alloc(), *convertedFrame = av_frame_alloc(), - *audioFrame = av_frame_alloc(), - *convertedAudioFrame = av_frame_alloc(); - AVPacket *packet = av_packet_alloc(); + av_frame_unref(convertedFrame); + av_frame_unref(convertedAudioFrame); + av_frame_unref(frame); + av_frame_unref(audioFrame); // A hard stop if we are out of frames to read while (av_read_frame(ctx, packet) >= 0) { @@ -211,13 +228,14 @@ std::pair> Video::loadNextFrame() { static_cast(packet->stream_index) == audioStreamNum) { avcodec_send_packet(aCodecCtx, packet); avcodec_receive_frame(aCodecCtx, audioFrame); + if (audioFrame->format != -1 && audioEngine) { convertedAudioFrame->format = sampleFormat; convertedAudioFrame->sample_rate = audioEngine->GetSampleRate(); convertedAudioFrame->ch_layout = outLayout; convertedAudioFrame->nb_samples = swr_get_out_samples(swrCtx, audioFrame->nb_samples); - av_frame_get_buffer(convertedAudioFrame, 0); + av_frame_get_buffer(convertedAudioFrame, 2); swr_convert_frame(swrCtx, convertedAudioFrame, audioFrame); @@ -227,18 +245,19 @@ std::pair> Video::loadNextFrame() { } if (static_cast(packet->stream_index) == videoStreamNum) { - // Requests a frame from the decoder avcodec_send_packet(vCodecCtx, packet); avcodec_receive_frame(vCodecCtx, frame); av_packet_unref(packet); - if (frame->format != -1) { + if (frame->format != AV_PIX_FMT_NONE) { frameSetScaleSAR(frame); frameFlip(frame); - frameConvert(frame, convertedFrame); + frameConvert(); break; } } + + // You don't know what you are doing, do not touch this av_packet_unref(packet); } @@ -252,11 +271,6 @@ std::pair> Video::loadNextFrame() { double ptsInSeconds = timeBase * frame->pts; // Cleanup time cus this is a C library yay (ironic) - av_frame_free(&convertedFrame); - av_frame_free(&convertedAudioFrame); - av_frame_free(&frame); - av_frame_free(&audioFrame); - av_packet_free(&packet); return {ptsInSeconds, std::move(data)}; } @@ -313,7 +327,7 @@ void Video::frameFlip(AVFrame *frame) { frame->linesize[2] = -frame->linesize[2]; } -void Video::frameConvert(AVFrame *sourceFrame, AVFrame *convertedFrame) { +void Video::frameConvert() { // Converting YUV420p to RGB24 convertedFrame->format = AV_PIX_FMT_RGB24; convertedFrame->colorspace = AVCOL_SPC_BT709; @@ -324,20 +338,16 @@ void Video::frameConvert(AVFrame *sourceFrame, AVFrame *convertedFrame) { 3); // Proper way to allocate space for data if (swsCtx == NULL) { - swsCtx = sws_getContext(Dimensions.x(), Dimensions.y(), - static_cast(sourceFrame->format), - Dimensions.x(), Dimensions.y(), - static_cast(convertedFrame->format), - SWS_BICUBIC, NULL, NULL, NULL); + swsCtx = sws_getContext(Dimensions.x(), Dimensions.y(), vCodecCtx->pix_fmt, + Dimensions.x(), Dimensions.y(), AV_PIX_FMT_RGB24, + SWS_BILINEAR, NULL, NULL, NULL); } - // TO DO: DO THIS PROPERLY - sws_setColorspaceDetails(swsCtx, sws_getCoefficients(SWS_CS_ITU709), - sourceFrame->color_range, - sws_getCoefficients(SWS_CS_ITU709), + sws_setColorspaceDetails(swsCtx, sws_getCoefficients(vCodecCtx->colorspace), + frame->color_range, + sws_getCoefficients(convertedFrame->colorspace), convertedFrame->color_range, 0, 1 << 16, 1 << 16); - // ----------------------------- - sws_scale(swsCtx, sourceFrame->data, sourceFrame->linesize, 0, Dimensions.y(), + sws_scale(swsCtx, frame->data, frame->linesize, 0, Dimensions.y(), convertedFrame->data, convertedFrame->linesize); } @@ -373,9 +383,13 @@ void Video::restartVideo() { void Video::dumpAndRefillBuffer() { std::map().swap(frameBuffer); - if (audioStreamNum != -1) { - Sound.release(); - Sound = audioEngine->CreateSound(10); - } + reinitSound(); loadTexture(loadNextFrame().second); } + +void Video::reinitSound() { + if (audioStreamNum != -1) { + delete Sound.release(); + Sound = std::move(audioEngine->CreateSound(10)); + } +}