diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 10bd54bf0..8ba0ddfc1 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -127,6 +127,17 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla } } + // Find the first audio stream + streamAudio = -1; + for(ui32 i=0; inb_streams; i++) + { + if (format->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + { + streamAudio = i; + break; + } + } + if (stream < 0) // No video stream in that file return false; @@ -134,6 +145,12 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla // Find the decoder for the video stream codec = avcodec_find_decoder(format->streams[stream]->codecpar->codec_id); + if(streamAudio > -1) + { + // Find the decoder for the audio stream + codecAudio = avcodec_find_decoder(format->streams[streamAudio]->codecpar->codec_id); + } + if (codec == nullptr) { // Unsupported codec @@ -143,6 +160,10 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla codecContext = avcodec_alloc_context3(codec); if(!codecContext) return false; + + if (codecAudio != nullptr) + codecContextAudio = avcodec_alloc_context3(codecAudio); + // Get a pointer to the codec context for the video stream int ret = avcodec_parameters_to_context(codecContext, format->streams[stream]->codecpar); if (ret < 0) @@ -152,6 +173,17 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla return false; } + // Get a pointer to the codec context for the audio stream + if (streamAudio > -1) + { + ret = avcodec_parameters_to_context(codecContextAudio, format->streams[streamAudio]->codecpar); + if (ret < 0) + { + //We cannot get codec from parameters + avcodec_free_context(&codecContextAudio); + } + } + // Open codec if ( avcodec_open2(codecContext, codec, nullptr) < 0 ) { @@ -162,6 +194,18 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla // Allocate video frame frame = av_frame_alloc(); + // Open codec + if (codecAudio != nullptr) + { + if ( avcodec_open2(codecContextAudio, codecAudio, nullptr) < 0 ) + { + // Could not open codec + codecAudio = nullptr; + } + // Allocate audio frame + frameAudio = av_frame_alloc(); + } + //setup scaling if(scale) { @@ -231,6 +275,8 @@ bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverla if (sws == nullptr) return false; + playVideoAudio(); + return true; } @@ -435,6 +481,30 @@ void CVideoPlayer::close() } } +void CVideoPlayer::playVideoAudio() +{ + AVPacket packet; + std::pair, si64> data; + + std::vector samples; + while (av_read_frame(format, &packet) >= 0) + { + avcodec_send_packet(codecContextAudio, &packet); + avcodec_receive_frame(codecContextAudio, frameAudio); + + data.second = frameAudio->linesize[0]; + data.first = (new ui8[data.second]); + + for (int s = 0; s < frameAudio->linesize[0]; s+=sizeof(ui8)) + { + ui8 value; + memcpy(&value, &frameAudio->data[0][s], sizeof(ui8)); + samples.push_back(value); + data.first. + } + } +} + // Plays a video. Only works for overlays. bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey) { diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index d447d64e6..155a1de57 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -23,6 +23,7 @@ public: virtual bool nextFrame()=0; virtual void show(int x, int y, SDL_Surface *dst, bool update = true)=0; virtual void redraw(int x, int y, SDL_Surface *dst, bool update = true)=0; //reblits buffer + virtual VideoPath videoName()=0; virtual bool wait()=0; virtual int curFrame() const =0; virtual int frameCount() const =0; @@ -46,6 +47,7 @@ public: void redraw( int x, int y, SDL_Surface *dst, bool update = true ) override {}; void show( int x, int y, SDL_Surface *dst, bool update = true ) override {}; bool nextFrame() override {return false;}; + VideoPath videoName() override {return VideoPath();}; void close() override {}; bool wait() override {return false;}; bool open(const VideoPath & name, bool scale = false) override {return false;}; @@ -66,10 +68,14 @@ VCMI_LIB_NAMESPACE_END class CVideoPlayer : public IMainVideoPlayer { int stream; // stream index in video + int streamAudio; // stream index in audio AVFormatContext *format; AVCodecContext *codecContext; // codec context for stream + AVCodecContext *codecContextAudio; // codec context for stream const AVCodec *codec; + const AVCodec *codecAudio; AVFrame *frame; + AVFrame *frameAudio; struct SwsContext *sws; AVIOContext * context; @@ -90,6 +96,7 @@ class CVideoPlayer : public IMainVideoPlayer bool playVideo(int x, int y, bool stopOnKey); bool open(const VideoPath & fname, bool loop, bool useOverlay = false, bool scale = false); + void playVideoAudio(); public: CVideoPlayer(); ~CVideoPlayer(); @@ -106,6 +113,8 @@ public: // Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played) bool openAndPlayVideo(const VideoPath & name, int x, int y, bool stopOnKey = false, bool scale = false) override; + VideoPath videoName() override {return fname;}; + //TODO: bool wait() override {return false;}; int curFrame() const override {return -1;};