@@ -54,6 +54,7 @@ static int read_file(const char *path, uint8_t **data, size_t *size) {
5454}
5555
5656static size_t find_access_units (const uint8_t * data , size_t size ,
57+ uint32_t codec ,
5758 struct access_unit * * units_out ) {
5859 size_t capacity = 64 ;
5960 size_t count = 0 ;
@@ -69,7 +70,12 @@ static size_t find_access_units(const uint8_t *data, size_t size,
6970 else if (i + 5 < size && data [i ] == 0 && data [i + 1 ] == 0 &&
7071 data [i + 2 ] == 0 && data [i + 3 ] == 1 )
7172 start_code = 4 ;
72- if (!start_code || (data [i + start_code ] & 0x1f ) != 9 )
73+ if (!start_code )
74+ continue ;
75+ uint32_t nal_type = codec == FMA_CODEC_HEVC ?
76+ (data [i + start_code ] >> 1 ) & 0x3f : data [i + start_code ] & 0x1f ;
77+ uint32_t aud_type = codec == FMA_CODEC_HEVC ? 35u : 9u ;
78+ if (nal_type != aud_type )
7379 continue ;
7480 if (found_aud ) {
7581 if (count == capacity ) {
@@ -98,6 +104,14 @@ static size_t find_access_units(const uint8_t *data, size_t size,
98104 return count ;
99105}
100106
107+ static uint32_t parse_codec (const char * name ) {
108+ if (strcmp (name , "h264" ) == 0 || strcmp (name , "avc" ) == 0 )
109+ return FMA_CODEC_H264 ;
110+ if (strcmp (name , "hevc" ) == 0 || strcmp (name , "h265" ) == 0 )
111+ return FMA_CODEC_HEVC ;
112+ return 0 ;
113+ }
114+
101115static int process_message (struct fma_client * client ,
102116 const struct fma_frame_pool * pool , uint8_t * pool_map ,
103117 FILE * output , uint64_t * frames , bool * packet_ack ,
@@ -137,40 +151,59 @@ static int process_message(struct fma_client *client,
137151}
138152
139153int main (int argc , char * * argv ) {
140- if (argc < 6 || argc > 7 ) {
141- fprintf (stderr , "usage: %s SOCKET INPUT.h264 WIDTH HEIGHT FPS [OUTPUT.nv12]\n" ,
142- argv [0 ]);
154+ uint32_t codec = FMA_CODEC_H264 ;
155+ uint32_t repeats = 1 ;
156+ int argument = 1 ;
157+ while (argument < argc && strncmp (argv [argument ], "--" , 2 ) == 0 ) {
158+ if (strcmp (argv [argument ], "--codec" ) == 0 && argument + 1 < argc ) {
159+ codec = parse_codec (argv [argument + 1 ]);
160+ argument += 2 ;
161+ } else if (strcmp (argv [argument ], "--repeat" ) == 0 && argument + 1 < argc ) {
162+ repeats = (uint32_t )strtoul (argv [argument + 1 ], NULL , 10 );
163+ argument += 2 ;
164+ } else {
165+ codec = 0 ;
166+ break ;
167+ }
168+ }
169+ int remaining = argc - argument ;
170+ if (!codec || !repeats || repeats > 1000 || remaining < 5 || remaining > 6 ) {
171+ fprintf (stderr , "usage: %s [--codec h264|hevc] [--repeat N] "
172+ "SOCKET INPUT WIDTH HEIGHT FPS [OUTPUT.nv12]\n" , argv [0 ]);
143173 return 2 ;
144174 }
145- uint32_t width = (uint32_t )strtoul (argv [3 ], NULL , 10 );
146- uint32_t height = (uint32_t )strtoul (argv [4 ], NULL , 10 );
147- uint32_t fps = (uint32_t )strtoul (argv [5 ], NULL , 10 );
175+ const char * socket_path = argv [argument + 0 ];
176+ const char * input_path = argv [argument + 1 ];
177+ uint32_t width = (uint32_t )strtoul (argv [argument + 2 ], NULL , 10 );
178+ uint32_t height = (uint32_t )strtoul (argv [argument + 3 ], NULL , 10 );
179+ uint32_t fps = (uint32_t )strtoul (argv [argument + 4 ], NULL , 10 );
180+ const char * output_path = remaining == 6 ? argv [argument + 5 ] : NULL ;
148181 if (!width || !height || !fps )
149182 return 2 ;
150183
151184 uint8_t * input = NULL ;
152185 size_t input_size = 0 ;
153- if (read_file (argv [ 2 ] , & input , & input_size ) < 0 ) {
186+ if (read_file (input_path , & input , & input_size ) < 0 ) {
154187 perror ("input" );
155188 return 1 ;
156189 }
157190 struct access_unit * units = NULL ;
158- size_t unit_count = find_access_units (input , input_size , & units );
191+ size_t unit_count = find_access_units (input , input_size , codec , & units );
159192 if (!unit_count ) {
160193 fprintf (stderr , "could not split input\n" );
161194 free (input );
162195 return 1 ;
163196 }
164197
165198 struct fma_client client ;
166- if (fma_client_connect (& client , argv [ 1 ] ) < 0 ) {
199+ if (fma_client_connect (& client , socket_path ) < 0 ) {
167200 perror ("connect" );
168201 free (units );
169202 free (input );
170203 return 1 ;
171204 }
172205 struct fma_decoder_config config = {
173- .codec = FMA_CODEC_H264 , .width = width , .height = height ,
206+ .codec = codec , .width = width , .height = height ,
174207 .slot_count = FMA_DEFAULT_SLOTS ,
175208 };
176209 struct fma_frame_pool pool ;
@@ -192,8 +225,8 @@ int main(int argc, char **argv) {
192225 free (input );
193226 return 1 ;
194227 }
195- FILE * output = argc == 7 ? fopen (argv [ 6 ] , "wb" ) : NULL ;
196- if (argc == 7 && !output ) {
228+ FILE * output = output_path ? fopen (output_path , "wb" ) : NULL ;
229+ if (output_path && !output ) {
197230 perror ("output" );
198231 return 1 ;
199232 }
@@ -204,35 +237,46 @@ int main(int argc, char **argv) {
204237 uint64_t started_ns = monotonic_ns ();
205238 bool eos = false;
206239 bool failed = false;
207- for (size_t i = 0 ; i < unit_count ; ++ i ) {
208- int64_t pts_us = (int64_t )(i * UINT64_C (1000000 ) / fps );
209- bool packet_ack = false;
210- if (fma_client_queue_packet (& client , input + units [i ].offset ,
211- units [i ].size , pts_us , 0 ) < 0 ) {
212- perror ("decode" );
213- failed = true;
214- break ;
240+ for (uint32_t repeat = 0 ; repeat < repeats && !failed ; ++ repeat ) {
241+ eos = false;
242+ for (size_t i = 0 ; i < unit_count ; ++ i ) {
243+ int64_t pts_us = (int64_t )(i * UINT64_C (1000000 ) / fps );
244+ bool packet_ack = false;
245+ if (fma_client_queue_packet (& client , input + units [i ].offset ,
246+ units [i ].size , pts_us , 0 ) < 0 ) {
247+ perror ("decode" );
248+ failed = true;
249+ break ;
250+ }
251+ input_bytes += units [i ].size ;
252+ while (!packet_ack &&
253+ process_message (& client , & pool , pool_map , output , & frames ,
254+ & packet_ack , & eos ) == 0 ) {}
255+ if (!packet_ack ) {
256+ perror ("decode" );
257+ failed = true;
258+ break ;
259+ }
215260 }
216- input_bytes += units [i ].size ;
217- while (!packet_ack &&
218- process_message (& client , & pool , pool_map , output , & frames ,
219- & packet_ack , & eos ) == 0 ) {}
220- if (!packet_ack ) {
221- perror ("decode" );
261+ if (!failed && fma_client_drain (& client ) == 0 ) {
262+ bool packet_ack = false;
263+ while (!eos && process_message (& client , & pool , pool_map , output ,
264+ & frames , & packet_ack , & eos ) == 0 ) {}
265+ }
266+ if (!eos )
267+ failed = true;
268+ if (!failed && repeat + 1 < repeats && fma_client_flush (& client ) < 0 ) {
269+ perror ("flush" );
222270 failed = true;
223- break ;
224271 }
225272 }
226- if (!failed && fma_client_drain (& client ) == 0 ) {
227- bool packet_ack = false;
228- while (!eos && process_message (& client , & pool , pool_map , output ,
229- & frames , & packet_ack , & eos ) == 0 ) {}
230- }
231273 uint64_t elapsed_ns = monotonic_ns () - started_ns ;
232274 frame_bytes = frames * pool .slot_size ;
233275 double seconds = elapsed_ns ? (double )elapsed_ns / 1000000000.0 : 0.0 ;
234- printf ("packets=%zu frames=%llu elapsed_ms=%.3f decode_fps=%.2f\n" ,
235- unit_count , (unsigned long long )frames , seconds * 1000.0 ,
276+ printf ("codec=%s repeats=%u packets=%zu frames=%llu elapsed_ms=%.3f "
277+ "decode_fps=%.2f\n" ,
278+ fma_codec_name (codec ), repeats , unit_count * (size_t )repeats ,
279+ (unsigned long long )frames , seconds * 1000.0 ,
236280 seconds > 0.0 ? (double )frames / seconds : 0.0 );
237281 printf ("compressed_bytes=%llu frame_bytes=%llu shared_pool_bytes=%zu "
238282 "socket_frame_bytes=0\n" ,
0 commit comments