1+ #include < stdio.h>
2+ #include < GLFW/glfw3.h>
3+
4+ #include " decoder.h"
5+ extern " C" {
6+ #include " tcp.h"
7+ #include < libgen.h>
8+ }
9+
10+ int main (int argc, const char ** argv) {
11+
12+ if (argc < 2 )
13+ {
14+ printf (" Usage: ./client filename\n " );
15+ return -1 ;
16+ }
17+
18+ if (!glfwInit ()) {
19+ err_log (" Couldn't init GLFW" );
20+ return 1 ;
21+ }
22+
23+ GLFWwindow *window;
24+ char *path = strdupa (argv[1 ]);
25+ const char *filename = basename (path);
26+
27+ // Should start download before preparing the window.
28+ // TODO: Synchronise the download and playback.
29+ run_tcp_client (path, filename);
30+
31+ decoder_t dec;
32+ if (!quicsy_decoder_open (&dec, filename)) {
33+ err_log (" Main Window: Couldn't open video file" );
34+ return 1 ;
35+ }
36+
37+ window = glfwCreateWindow (dec.width , dec.height , " QUIC streamer" , NULL , NULL );
38+ if (!window) {
39+ err_log (" Couldn't open window" );
40+ return 1 ;
41+ }
42+
43+ log (" opening the input file (%s) and loading format (container) header" , argv[1 ]);
44+
45+ glfwMakeContextCurrent (window);
46+
47+ // Generate texture
48+ GLuint tex_handle;
49+ glGenTextures (1 , &tex_handle);
50+ glBindTexture (GL_TEXTURE_2D, tex_handle);
51+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1 );
52+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
53+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
54+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
55+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
56+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
57+
58+ // Allocate frame buffer
59+ const int frame_width = dec.width ;
60+ const int frame_height = dec.height ;
61+ uint8_t * frame_data = new uint8_t [frame_width * frame_height * 4 ];
62+
63+ while (!glfwWindowShouldClose (window)) {
64+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65+
66+ // Set up orphographic projection
67+ int window_width, window_height;
68+ glfwGetFramebufferSize (window, &window_width, &window_height);
69+ glMatrixMode (GL_PROJECTION);
70+ glLoadIdentity ();
71+ glOrtho (0 , window_width, window_height, 1 , -1 , 1 );
72+ glMatrixMode (GL_MODELVIEW);
73+ // Read a new frame and load it into texture
74+ int64_t pts;
75+ if (!quicsy_decoder_read_frame (&dec, frame_data, &pts)) {
76+ err_log (" Couldn't load video frame\n " );
77+ return 1 ;
78+ }
79+
80+ static bool first_frame = true ;
81+ if (first_frame) {
82+ glfwSetTime (0.0 );
83+ first_frame = false ;
84+ }
85+
86+ double pt_in_seconds = pts * (double )dec.time_base .num / (double )dec.time_base .den ;
87+ while (pt_in_seconds > glfwGetTime ()) {
88+ glfwWaitEventsTimeout (pt_in_seconds - glfwGetTime ());
89+ }
90+
91+ glBindTexture (GL_TEXTURE_2D, tex_handle);
92+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGB, frame_width, frame_height, 0 , GL_RGBA, GL_UNSIGNED_BYTE, frame_data);
93+
94+ // Render whatever you want
95+ glEnable (GL_TEXTURE_2D);
96+ glBindTexture (GL_TEXTURE_2D, tex_handle);
97+ glBegin (GL_QUADS);
98+ glTexCoord2d (0 , 0 );
99+ glVertex2i (0 ,0 );
100+ glTexCoord2d (1 , 0 );
101+ glVertex2i (window_width, 0 );
102+ glTexCoord2d (1 , 1 );
103+ glVertex2i (window_width, window_height);
104+ glTexCoord2d (0 , 1 );
105+ glVertex2i (0 , window_height);
106+ glEnd ();
107+ glDisable (GL_TEXTURE_2D);
108+
109+ glfwSwapBuffers (window);
110+ glfwPollEvents ();
111+ }
112+
113+ quicsy_decoder_close (&dec);
114+
115+ if (remove (filename) < 0 )
116+ {
117+ printf (" Unable to delete file" );
118+ }
119+
120+ return 0 ;
121+ }
0 commit comments