11#include "decoder.h"
22
33#include <libavformat/avformat.h>
4+ #include <libavutil/time.h>
5+ #include <SDL2/SDL_assert.h>
46#include <SDL2/SDL_events.h>
57#include <SDL2/SDL_mutex.h>
68#include <SDL2/SDL_thread.h>
79#include <unistd.h>
810
911#include "config.h"
12+ #include "buffer_util.h"
1013#include "events.h"
1114#include "frames.h"
1215#include "lock_util.h"
1316#include "log.h"
17+ #include "recorder.h"
1418
1519#define BUFSIZE 0x10000
1620
17- static int read_packet (void * opaque , uint8_t * buf , int buf_size ) {
21+ #define HEADER_SIZE 12
22+ #define NO_PTS UINT64_C(-1)
23+
24+ static struct frame_meta * frame_meta_new (uint64_t pts ) {
25+ struct frame_meta * meta = malloc (sizeof (* meta ));
26+ if (!meta ) {
27+ return meta ;
28+ }
29+ meta -> pts = pts ;
30+ meta -> next = NULL ;
31+ return meta ;
32+ }
33+
34+ static void frame_meta_delete (struct frame_meta * frame_meta ) {
35+ free (frame_meta );
36+ }
37+
38+ static SDL_bool receiver_state_push_meta (struct receiver_state * state ,
39+ uint64_t pts ) {
40+ struct frame_meta * frame_meta = frame_meta_new (pts );
41+ if (!frame_meta ) {
42+ return SDL_FALSE ;
43+ }
44+
45+ // append to the list
46+ // (iterate to find the last item, in practice the list should be tiny)
47+ struct frame_meta * * p = & state -> frame_meta_queue ;
48+ while (* p ) {
49+ p = & (* p )-> next ;
50+ }
51+ * p = frame_meta ;
52+ return SDL_TRUE ;
53+ }
54+
55+ static uint64_t receiver_state_take_meta (struct receiver_state * state ) {
56+ struct frame_meta * frame_meta = state -> frame_meta_queue ; // first item
57+ SDL_assert (frame_meta ); // must not be empty
58+ uint64_t pts = frame_meta -> pts ;
59+ state -> frame_meta_queue = frame_meta -> next ; // remove the item
60+ frame_meta_delete (frame_meta );
61+ return pts ;
62+ }
63+
64+ static int read_packet_with_meta (void * opaque , uint8_t * buf , int buf_size ) {
65+ struct decoder * decoder = opaque ;
66+ struct receiver_state * state = & decoder -> receiver_state ;
67+
68+ // The video stream contains raw packets, without time information. When we
69+ // record, we retrieve the timestamps separately, from a "meta" header
70+ // added by the server before each raw packet.
71+ //
72+ // The "meta" header length is 12 bytes:
73+ // [. . . . . . . .|. . . .]. . . . . . . . . . . . . . . ...
74+ // <-------------> <-----> <-----------------------------...
75+ // PTS packet raw packet
76+ // size
77+ //
78+ // It is followed by <packet_size> bytes containing the packet/frame.
79+
80+ if (!state -> remaining ) {
81+ #define HEADER_SIZE 12
82+ uint8_t header [HEADER_SIZE ];
83+ ssize_t ret = net_recv_all (decoder -> video_socket , header , HEADER_SIZE );
84+ if (ret <= 0 ) {
85+ return ret ;
86+ }
87+ // no partial read (net_recv_all())
88+ SDL_assert_release (ret == HEADER_SIZE );
89+
90+ uint64_t pts = buffer_read64be (header );
91+ state -> remaining = buffer_read32be (& header [8 ]);
92+
93+ if (pts != NO_PTS && !receiver_state_push_meta (state , pts )) {
94+ LOGE ("Could not store PTS for recording" );
95+ // we cannot save the PTS, the recording would be broken
96+ return -1 ;
97+ }
98+ }
99+
100+ SDL_assert (state -> remaining );
101+
102+ if (buf_size > state -> remaining )
103+ buf_size = state -> remaining ;
104+
105+ ssize_t ret = net_recv (decoder -> video_socket , buf , buf_size );
106+ if (ret <= 0 ) {
107+ return ret ;
108+ }
109+
110+ SDL_assert (state -> remaining >= ret );
111+ state -> remaining -= ret ;
112+
113+ return ret ;
114+ }
115+
116+ static int read_raw_packet (void * opaque , uint8_t * buf , int buf_size ) {
18117 struct decoder * decoder = opaque ;
19118 return net_recv (decoder -> video_socket , buf , buf_size );
20119}
@@ -70,7 +169,15 @@ static int run_decoder(void *data) {
70169 goto run_finally_free_format_ctx ;
71170 }
72171
73- AVIOContext * avio_ctx = avio_alloc_context (buffer , BUFSIZE , 0 , decoder , read_packet , NULL , NULL );
172+ // initialize the receiver state
173+ decoder -> receiver_state .frame_meta_queue = NULL ;
174+ decoder -> receiver_state .remaining = 0 ;
175+
176+ // if recording is enabled, a "header" is sent between raw packets
177+ int (* read_packet )(void * , uint8_t * , int ) =
178+ decoder -> recorder ? read_packet_with_meta : read_raw_packet ;
179+ AVIOContext * avio_ctx = avio_alloc_context (buffer , BUFSIZE , 0 , decoder ,
180+ read_packet , NULL , NULL );
74181 if (!avio_ctx ) {
75182 LOGC ("Could not allocate avio context" );
76183 // avformat_open_input takes ownership of 'buffer'
@@ -86,6 +193,12 @@ static int run_decoder(void *data) {
86193 goto run_finally_free_avio_ctx ;
87194 }
88195
196+ if (decoder -> recorder &&
197+ !recorder_open (decoder -> recorder , codec )) {
198+ LOGE ("Could not open recorder" );
199+ goto run_finally_close_input ;
200+ }
201+
89202 AVPacket packet ;
90203 av_init_packet (& packet );
91204 packet .data = NULL ;
@@ -125,6 +238,23 @@ static int run_decoder(void *data) {
125238 packet .data += len ;
126239 }
127240#endif
241+
242+ if (decoder -> recorder ) {
243+ // we retrieve the PTS in order they were received, so they will
244+ // be assigned to the correct frame
245+ uint64_t pts = receiver_state_take_meta (& decoder -> receiver_state );
246+ packet .pts = pts ;
247+ packet .dts = pts ;
248+
249+ // no need to rescale with av_packet_rescale_ts(), the timestamps
250+ // are in microseconds both in input and output
251+ if (!recorder_write (decoder -> recorder , & packet )) {
252+ LOGE ("Could not write frame to output file" );
253+ av_packet_unref (& packet );
254+ goto run_quit ;
255+ }
256+ }
257+
128258 av_packet_unref (& packet );
129259
130260 if (avio_ctx -> eof_reached ) {
@@ -135,6 +265,10 @@ static int run_decoder(void *data) {
135265 LOGD ("End of frames" );
136266
137267run_quit :
268+ if (decoder -> recorder ) {
269+ recorder_close (decoder -> recorder );
270+ }
271+ run_finally_close_input :
138272 avformat_close_input (& format_ctx );
139273run_finally_free_avio_ctx :
140274 av_freep (& avio_ctx );
@@ -149,9 +283,11 @@ static int run_decoder(void *data) {
149283 return 0 ;
150284}
151285
152- void decoder_init (struct decoder * decoder , struct frames * frames , socket_t video_socket ) {
286+ void decoder_init (struct decoder * decoder , struct frames * frames ,
287+ socket_t video_socket , struct recorder * recorder ) {
153288 decoder -> frames = frames ;
154289 decoder -> video_socket = video_socket ;
290+ decoder -> recorder = recorder ;
155291}
156292
157293SDL_bool decoder_start (struct decoder * decoder ) {
@@ -162,7 +298,6 @@ SDL_bool decoder_start(struct decoder *decoder) {
162298 LOGC ("Could not start decoder thread" );
163299 return SDL_FALSE ;
164300 }
165-
166301 return SDL_TRUE ;
167302}
168303
0 commit comments