X-Git-Url: http://47.100.26.94:8080/?a=blobdiff_plain;f=yuvPlayer.cpp;h=fe7f45e7540a8e8ab51092117d9aed24d8d7f931;hb=88edf5d3b8e5a0b6776e2d8eb6640823b324f3ef;hp=322975e798a3dd109074c33748d56a5aede6440f;hpb=7de7c3da29277838e63b63ffd2512b4014b90fa7;p=yuv-player.git diff --git a/yuvPlayer.cpp b/yuvPlayer.cpp index 322975e..fe7f45e 100644 --- a/yuvPlayer.cpp +++ b/yuvPlayer.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "SDL2/SDL.h" using namespace std; @@ -11,13 +14,19 @@ using namespace std; * Play YUV with ffplay * ffplay -f rawvideo -pixel_format yuv420p -video_size 1280x720 -i ./out.yuv * + * Usage: + * 1. press 'P' to pause or play as the given framerate + * 2. press 'q' to quit + * 3. press RIGHT to next frame, LEFT to previous frame + * 4. color space transform */ class YuvPlayer { public: - YuvPlayer(int width, int height); - void play(string fname); + YuvPlayer(int width, int height, const string& title = "YUV Player"); + void play(string fname, int fps = -1); + void toggleGrid(); ~YuvPlayer(); private: @@ -29,14 +38,32 @@ private: SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *texture; + unsigned int frameCnt = 0; + string title; + ifstream::pos_type last_pos; + bool isShowingGrid = false; + uint8_t *raw; }; -YuvPlayer::YuvPlayer(int w, int h) + +class ImageOperation { +public: + ImageOperation(uint8_t *r, int width, int height); + + +private: + int width; + int height; + uint8_t *raw; +}; + +YuvPlayer::YuvPlayer(int w, int h, const string& t) : width(w) , height(h) +, title(t) { SDL_Init(SDL_INIT_VIDEO); - window = SDL_CreateWindow("YUV Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); + window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); if (window == nullptr){ cout << "create error: " << SDL_GetError() << endl; } @@ -46,23 +73,35 @@ YuvPlayer::YuvPlayer(int w, int h) YuvPlayer::~YuvPlayer() { + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } -void YuvPlayer::play(string file) +void YuvPlayer::play(string file, int fps) { size_t frame_size = width * height * 3 / 2; - uint8_t *raw = (uint8_t *) malloc(sizeof(uint8_t) * frame_size); + raw = (uint8_t *) malloc(sizeof(uint8_t) * frame_size); ifstream in (file, ios::binary); if (!in.is_open()) { cout << "failed to open " << file << endl; } + SDL_Event event; bool quit = false; + bool isPlaying = true; + int interval = 1000 / fps; + while(!quit) { - SDL_WaitEvent(&event); + interval = isPlaying ? 1000 / fps : -1; + SDL_WaitEventTimeout(&event, interval); + if(fps > 0 && isPlaying){ + if(readFrame(in, raw, frame_size)){ + updateRenderer(raw); + } + } switch(event.type){ case SDL_QUIT: quit = true; @@ -73,8 +112,23 @@ void YuvPlayer::play(string file) quit = true; break; case SDLK_RIGHT: - readFrame(in, raw, frame_size); - updateRenderer(raw); + if(readFrame(in, raw, frame_size)){ + updateRenderer(raw); + } + break; + case SDLK_LEFT: + frameCnt = frameCnt >= 2 ? frameCnt - 2 : 0; + in.seekg(frameCnt * frame_size); + if(readFrame(in, raw, frame_size)){ + updateRenderer(raw); + } + + break; + case SDLK_p: + isPlaying = !isPlaying; + break; + case SDLK_g: + toggleGrid(); break; default: break; @@ -86,10 +140,26 @@ void YuvPlayer::play(string file) free(raw); } +void YuvPlayer::toggleGrid() +{ + isShowingGrid = !isShowingGrid; + updateRenderer(raw); +} + + bool YuvPlayer::readFrame(ifstream& in, uint8_t *raw, size_t size) { - in.read(reinterpret_cast(raw), size); - return true; + last_pos = in.tellg(); + bool ret = (bool) in.read(reinterpret_cast(raw), size); + if (ret){ + frameCnt++; + stringstream ss; + ss << this->title << " [" << setw(4) << to_string(frameCnt) << "]"; + SDL_SetWindowTitle(window, ss.str().c_str()); + }else { + cout << "read error" << endl; + } + return ret; } void YuvPlayer::updateRenderer(uint8_t *raw) @@ -97,12 +167,25 @@ void YuvPlayer::updateRenderer(uint8_t *raw) SDL_UpdateTexture(texture, nullptr, raw, width * SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_IYUV)); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, nullptr); + + if(isShowingGrid){ + SDL_SetRenderDrawColor( renderer, 0x00, 0x00, 0xFF, 0xFF ); + //SDL_RenderDrawLine( renderer, 0, height / 2, width, height / 2 ); + SDL_RenderDrawLine( renderer, 0, height / 3, width, height / 3 ); + SDL_RenderDrawLine( renderer, 0, height * 2 / 3, width, height * 2 / 3 ); + + SDL_RenderDrawLine( renderer, width / 3, 0, width / 3, height ); + SDL_RenderDrawLine( renderer, width * 2 / 3, 0, width * 2 / 3, height ); + + } + SDL_RenderPresent(renderer); } -int main() +int main(int argc, char* argv[]) { string fname = "out.yuv"; YuvPlayer player(1280, 720); - player.play(fname); + player.play(fname, 25); + //player.play(fname); }