2 * Copyright (c) 2008 Luca Abeni
4 * This is free software; see GPL.txt
11 #include <libavformat/avformat.h>
12 #include <libavdevice/avdevice.h>
13 #include <libswscale/swscale.h>
20 #include "streamer_config.h"
24 #include <ul_logreg.h>
27 #ifdef CONFIG_FFMPEG_WITH_FRSH
30 /*temporrary solution to pass network parameters */
31 extern long int frsh_rtp_budget, frsh_rtp_period_ms, frsh_rtp_deadline_ms;
32 #endif /*CONFIG_STREAMER_WITH_FRSH*/
34 static const char *sdp_file = "sdp.txt";
35 static const char *vdev = "/dev/video0";
36 static const char *dst = "127.0.0.1";
37 static int dport = 20000;
38 static int width = 320;
39 static int height = 240;
40 static int bitrate = 1000000;
42 static const char *impform = "video4linux2";
43 AVFormatContext *s, *os;
45 static void sdp_print(AVFormatContext *s, const char *fname)
50 f = fopen(fname, "w");
51 avf_sdp_create(&s, 1, sdp, sizeof(sdp));
52 fprintf(f, "%s\n", sdp);
59 printf("usage: streamer [ options ]\n");
60 printf(" -w <number> send image width\n");
61 printf(" -h <number> send image height\n");
62 printf(" -r <number> refresh rate\n");
63 printf(" -r <path> video device [%s]\n", vdev);
64 printf(" -m <addr> destination IP address\n");
65 printf(" -i <string> input video device format [%s]\n", impform);
66 printf(" -p <port> destination port [%d]\n", dport);
67 printf(" -b <bitrate> bitrate in b/s [%d]\n", bitrate);
68 printf(" -s <sdp_file> name of output sdp file [%s]\n", sdp_file);
70 printf(" -l <number>|<domain>=<number>,...\n");
71 #endif /*CONFIG_OC_ULUT*/
74 static int args_parse(int argc, char *argv[])
78 while ((v = getopt(argc, argv, "w:h:r:d:m:i:l:b:p:s:")) >= 0) {
90 height = atoi(optarg);
96 bitrate = atoi(optarg);
106 if(!strcmp(impform, "v4l"))
107 impform = "video4linux";
108 else if(!strcmp(impform, "v4l2"))
109 impform = "video4linux2";
111 #ifdef CONFIG_OC_ULUT
113 ul_log_domain_arg2levels(optarg);
115 #endif /*CONFIG_OC_ULUT*/
117 default: /* unknown option */
118 fprintf(stderr, "%s: illegal option %c\n", argv[0], v);
127 int streamer_run_done_rq;
130 timespec_subtract (struct timespec *result,
134 /* Perform the carry for the later subtraction by updating Y. */
135 if (x->tv_nsec < y->tv_nsec) {
136 int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
137 y->tv_nsec -= 1000000000 * num_sec;
138 y->tv_sec += num_sec;
140 if (x->tv_nsec - y->tv_nsec > 1000000000) {
141 int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
142 y->tv_nsec += 1000000000 * num_sec;
143 y->tv_sec -= num_sec;
146 /* Compute the time remaining to wait.
147 `tv_nsec' is certainly positive. */
148 result->tv_sec = x->tv_sec - y->tv_sec;
149 result->tv_nsec = x->tv_nsec - y->tv_nsec;
151 /* Return 1 if result is negative. */
152 return x->tv_sec < y->tv_sec;
156 void* streamer_run(void* args)
161 struct timespec start, end, d;
162 static unsigned max_size = 0, min_size = -1;
163 static double avg_size = 0;
164 clock_gettime(CLOCK_MONOTONIC, &start);
165 start.tv_sec--; /* Avoid division by zero */
167 while (!(done = streamer_run_done_rq)) {
169 pkt = read_input_packet(s);
171 clock_gettime(CLOCK_MONOTONIC, &end);
172 timespec_subtract(&d, &end, &start);
174 int fps_now = (1000<<16)/(d.tv_sec*1000+d.tv_nsec/1000000);
175 fps_avg += (fps_now - fps_avg) >> 4;
183 pkt->pts += s->streams[pkt->stream_index]->start_time;
184 //rt_job_start(pkt->pts);
185 f = pkt_decode(s, pkt);
187 opkt = pkt_encode(os, f);
191 if (opkt->size > max_size)
192 max_size = opkt->size;
193 if (opkt->size < min_size)
194 min_size = opkt->size;
195 avg_size = avg_size*frame/(frame+1) + (double)opkt->size/(frame+1);
196 printf("%5d: %2d (%4.1f) fps opkt size: %5d b max=%5u b min=%5u b avg=%5.0f\n",
198 fps_avg>>16, 1000.0/(d.tv_sec*1000+d.tv_nsec/1000000),
199 opkt->size, max_size, min_size, avg_size);
200 if (frame % 100 == 0) max_size=0;
201 frame++;// = (frame + 1) % fps;
212 void wait_for_ending_command(void) {
214 sigemptyset(&sigset);
215 sigaddset(&sigset, SIGINT);
216 sigaddset(&sigset, SIGTERM);
217 sigwaitinfo(&sigset, NULL);
219 static void block_signals(void) {
221 sigemptyset(&sigset);
222 sigaddset(&sigset, SIGINT);
223 sigaddset(&sigset, SIGTERM);
224 sigprocmask(SIG_BLOCK,&sigset,NULL);
225 pthread_sigmask(SIG_BLOCK,&sigset,NULL);
229 int main(int argc, char *argv[])
232 //long int cpu_budget, cpu_period;
237 #ifdef CONFIG_FFMPEG_WITH_FRSH
239 if (ret) PERROR_AND_EXIT(ret, "frsh_init1");
241 /* fill default network contract params */
242 frsh_rtp_budget = 100*bitrate/8/100;
243 frsh_rtp_period_ms = 1000;
244 frsh_rtp_deadline_ms = 1000/fps;
245 #endif /*CONFIG_FFMPEG_WITH_FRSH*/
247 avcodec_register_all();
249 avdevice_register_all();
251 args_parse(argc, argv);
253 s = open_input_stream(vdev, width, height, fps, impform);
255 fprintf(stderr, "Cannot open input file %s\n", vdev);
260 os = open_output_stream(dst, dport, CODEC_TYPE_VIDEO, fps);
262 fprintf(stderr, "Cannot open output stream\n");
266 os->streams[0]->codec->width = s->streams[0]->codec->width;
267 os->streams[0]->codec->height = s->streams[0]->codec->height;
268 os->streams[0]->codec->time_base = s->streams[0]->codec->time_base;
269 os->streams[0]->codec->bit_rate = bitrate;
270 codec_connect(s->streams[0]->codec, os->streams[0]->codec);
272 dump_format(os, 0, os->filename, 1);
273 sdp_print(os, sdp_file);
275 #if CONFIG_FFMPEG_WITH_FRSH && CONFIG_AQUOSA
276 frsh_thread_attr_t frsh_attr;
277 frsh_thread_id_t thread;
278 frsh_vres_id_t cpu_vres;
279 frsh_contract_t cpu_contract;
280 frsh_rel_time_t cpu_budget, cpu_period;
282 cpu_budget = fosa_msec_to_rel_time(10);
283 cpu_period = fosa_msec_to_rel_time(1000/fps);
284 /* Contract negotiation for CPU */
285 ret = frsh_contract_init(&cpu_contract);
286 if (ret) PERROR_AND_EXIT(ret, "CPU:frsh_contract_init");
288 ret = frsh_contract_set_basic_params(&cpu_contract,
293 if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
294 ret = frsh_contract_set_resource_and_label(&cpu_contract,
295 FRSH_RT_PROCESSOR, FRSH_CPU_ID_DEFAULT, "aqcpu_cont");
296 if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
298 ret = frsh_contract_negotiate(&cpu_contract, &cpu_vres);
299 if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
300 printf("Aqcpu vres negotiated\n");
302 pthread_attr_init(&frsh_attr);
303 ret = frsh_thread_create_and_bind(cpu_vres, &thread, &frsh_attr,
304 streamer_run, (void*) NULL);
305 if (ret) PERROR_AND_EXIT(ret, "frsh_thread_create_and_bind");
307 wait_for_ending_command();
309 streamer_run_done_rq = 1;
311 pthread_join(thread.pthread_id, (void**) NULL);
313 printf("Ending contracts\n");
315 ret = frsh_contract_cancel(cpu_vres);
316 if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
318 printf("Finishing\n");
320 close_output_stream(os);
323 pthread_t streamer_th;
325 pthread_attr_init(&attr);
327 ret = pthread_create(&streamer_th, &attr, streamer_run, (void*) NULL);
329 printf("Failed to create streamer thread\n.");
331 wait_for_ending_command();
333 streamer_run_done_rq = 1;
335 pthread_join(streamer_th, (void**) NULL);
337 printf("Finishing\n");
339 close_output_stream(os);