Added some code for displaying video frames with SDL2
This commit is contained in:
parent
94d70b6ce6
commit
c005ce08c2
@ -1,16 +1,79 @@
|
|||||||
#include "ffcpp/Player.h"
|
#include "ffcpp/Player.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_thread.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace ff = ffcpp;
|
namespace ff = ffcpp;
|
||||||
|
|
||||||
class SDLWindow: public ff::IVideoSink {
|
#define WINDOW_WIDTH 640
|
||||||
|
#define WINDOW_HEIGHT 480
|
||||||
|
|
||||||
|
class SDLWindow: public ff::IVideoSink {
|
||||||
|
private:
|
||||||
|
template<typename T> using SDLUniquePtr = std::unique_ptr<T, DECLSPEC void SDLCALL(*)(T*)>;
|
||||||
|
using SDLWindowPtr = SDLUniquePtr<SDL_Window>;
|
||||||
|
using SDLRendererPtr = SDLUniquePtr<SDL_Renderer>;
|
||||||
|
using SDLTexturePtr = SDLUniquePtr<SDL_Texture>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDLWindowPtr _wnd;
|
||||||
|
SDLRendererPtr _renderer;
|
||||||
|
SDLTexturePtr _texture;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SDLWindow(): _wnd(nullptr, SDL_DestroyWindow), _renderer(nullptr, SDL_DestroyRenderer), _texture(nullptr, SDL_DestroyTexture) {
|
||||||
|
int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
|
||||||
|
if(res < 0) throw std::runtime_error("Error initializing SDL");
|
||||||
|
|
||||||
|
_wnd.reset(SDL_CreateWindow("ffPlayer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL));
|
||||||
|
if(!_wnd) throw std::runtime_error("Error creating SDL window");
|
||||||
|
|
||||||
|
_renderer.reset(SDL_CreateRenderer(_wnd.get(), -1, 0));
|
||||||
|
if(!_renderer) throw std::runtime_error("Error creating SDL renderer");
|
||||||
|
|
||||||
|
_texture.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, WINDOW_WIDTH, WINDOW_HEIGHT));
|
||||||
|
if(!_texture) throw std::runtime_error("Error creating SDL texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual AVPixelFormat getPixelFormat() const noexcept override {
|
||||||
|
return AV_PIX_FMT_YUV420P;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getWidth() const noexcept override {
|
||||||
|
return WINDOW_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getHeight() const noexcept override {
|
||||||
|
return WINDOW_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawFrame(void* pixelsData, int pitch) override {
|
||||||
|
std::cout << "drawing frame" << std::endl;
|
||||||
|
SDL_UpdateTexture(_texture.get(), nullptr, pixelsData, pitch);
|
||||||
|
SDL_RenderClear(_renderer.get());
|
||||||
|
SDL_RenderCopy(_renderer.get(), _texture.get(), nullptr, nullptr);
|
||||||
|
SDL_RenderPresent(_renderer.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawPlanarYUVFrame(const void *yPlane, const void *uPlane, const void *vPlane, int yPitch, int uPitch, int vPitch) override {
|
||||||
|
SDL_UpdateYUVTexture(_texture.get(), nullptr, (const uint8_t*)yPlane, yPitch, (const uint8_t*)uPlane, uPitch, (const uint8_t*)vPlane, vPitch);
|
||||||
|
SDL_RenderClear(_renderer.get());
|
||||||
|
SDL_RenderCopy(_renderer.get(), _texture.get(), nullptr, nullptr);
|
||||||
|
SDL_RenderPresent(_renderer.get());
|
||||||
|
//std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
auto wnd = std::make_shared<SDLWindow>();
|
auto wnd = std::make_shared<SDLWindow>();
|
||||||
ff::Player player(wnd);
|
ff::Player player(wnd);
|
||||||
player.setMedia(argv[1]);
|
player.setMedia(argv[1]);
|
||||||
|
player.play();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -7,7 +7,12 @@
|
|||||||
namespace ffcpp {
|
namespace ffcpp {
|
||||||
|
|
||||||
struct IVideoSink {
|
struct IVideoSink {
|
||||||
|
virtual AVPixelFormat getPixelFormat() const noexcept = 0;
|
||||||
|
virtual int getWidth() const noexcept = 0;
|
||||||
|
virtual int getHeight() const noexcept = 0;
|
||||||
|
virtual void drawFrame(void* pixelsData, int pitch) = 0;
|
||||||
|
virtual void drawPlanarYUVFrame(const void *yPlane, const void *uPlane, const void *vPlane, int yPitch,
|
||||||
|
int uPitch, int vPitch) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "ffcpp/Player.h"
|
#include "ffcpp/Player.h"
|
||||||
#include "ffcpp/Stream.h"
|
#include "ffcpp/Stream.h"
|
||||||
|
#include "ffcpp/Scaler.h"
|
||||||
|
|
||||||
namespace ffcpp {
|
namespace ffcpp {
|
||||||
|
|
||||||
@ -17,15 +18,26 @@ namespace ffcpp {
|
|||||||
|
|
||||||
_vStream = _curMedia->videoStream();
|
_vStream = _curMedia->videoStream();
|
||||||
_aStream = _curMedia->audioStream();
|
_aStream = _curMedia->audioStream();
|
||||||
|
|
||||||
auto vDecoder = _vStream->codec();
|
|
||||||
auto aDecoder = _aStream->codec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::play() {
|
void Player::play() {
|
||||||
if(!_curMedia)
|
if(!_curMedia)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto vDecoder = _vStream->codec();
|
||||||
|
auto aDecoder = _aStream->codec();
|
||||||
|
|
||||||
|
Scaler scaler(vDecoder->width(), vDecoder->height(), vDecoder->pixelFormat(),
|
||||||
|
_vSink->getWidth(), _vSink->getHeight(), _vSink->getPixelFormat());
|
||||||
|
while(auto packet = _curMedia->readPacket()) {
|
||||||
|
AVMediaType packetType = _curMedia->packetType(packet);
|
||||||
|
if(packetType == AVMEDIA_TYPE_VIDEO) {
|
||||||
|
auto frame = vDecoder->decode(packet);
|
||||||
|
frame = scaler.scale(frame);
|
||||||
|
AVFrame* f = frame;
|
||||||
|
//_vSink->drawFrame(f->data, f->linesize[0]);
|
||||||
|
_vSink->drawPlanarYUVFrame(f->data[0], f->data[1], f->data[2], f->linesize[0], f->linesize[1], f->linesize[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user