322975e798a3dd109074c33748d56a5aede6440f
[yuv-player.git] / yuvPlayer.cpp
1 #include<iostream>
2 #include<fstream>
3 #include "SDL2/SDL.h"
4
5 using namespace std;
6
7 /*
8  * Convert MP4 to YUV
9  * ffmpeg -i big_buck_bunny_720p_10mb.mp4 -c:v rawvideo -pix_fmt yuv420p out.yuv
10  *
11  * Play YUV with ffplay
12  * ffplay -f rawvideo -pixel_format yuv420p -video_size 1280x720 -i ./out.yuv
13  *
14  */
15
16 class YuvPlayer 
17 {
18 public:
19     YuvPlayer(int width, int height);
20     void play(string fname);
21     ~YuvPlayer();
22
23 private:
24     bool readFrame(ifstream& in, uint8_t *raw, size_t size);
25     void updateRenderer(uint8_t *raw);
26     string file;
27     int width = 1280;
28     int height = 720;
29     SDL_Window *window;
30     SDL_Renderer *renderer;
31     SDL_Texture *texture;
32 };
33
34 YuvPlayer::YuvPlayer(int w, int h)
35 : width(w)
36 , height(h)
37 {
38     SDL_Init(SDL_INIT_VIDEO);
39     window = SDL_CreateWindow("YUV Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
40     if (window == nullptr){
41         cout << "create error: " << SDL_GetError() << endl;
42     }
43     renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
44     texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, width, height);
45 }
46
47 YuvPlayer::~YuvPlayer()
48 {
49     SDL_DestroyWindow(window);
50     SDL_Quit();
51 }
52
53 void YuvPlayer::play(string file)
54 {
55     size_t frame_size = width * height * 3 / 2;
56     uint8_t *raw = (uint8_t *) malloc(sizeof(uint8_t) * frame_size);
57     ifstream in (file, ios::binary);
58     if (!in.is_open()) {
59         cout << "failed to open " << file << endl;
60     }
61
62     SDL_Event event;
63     bool quit = false;
64     while(!quit) {
65         SDL_WaitEvent(&event);
66         switch(event.type){
67             case SDL_QUIT:
68                 quit = true;
69                 break;
70             case SDL_KEYDOWN:
71                 switch(event.key.keysym.sym){
72                     case SDLK_q:
73                         quit = true;
74                         break;
75                     case SDLK_RIGHT:
76                         readFrame(in, raw, frame_size);
77                         updateRenderer(raw);
78                         break;
79                     default:
80                         break;
81                 }
82             default:
83                 break;
84         }
85     }
86     free(raw);
87 }
88
89 bool YuvPlayer::readFrame(ifstream& in, uint8_t *raw, size_t size)
90 {
91     in.read(reinterpret_cast<char *>(raw), size);
92     return true;
93 }
94
95 void YuvPlayer::updateRenderer(uint8_t *raw)
96 {    
97     SDL_UpdateTexture(texture, nullptr, raw, width * SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_IYUV));
98     SDL_RenderClear(renderer);
99     SDL_RenderCopy(renderer, texture, nullptr, nullptr);
100     SDL_RenderPresent(renderer);
101 }
102
103 int main()
104 {
105     string fname = "out.yuv";
106     YuvPlayer player(1280, 720);
107     player.play(fname);
108 }