From 2fd032b55cf1b0136923f2a5b7e6286b0ef292d4 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Tue, 10 Sep 2013 13:59:21 +0200 Subject: [PATCH 01/57] muxer starting point --- Makefile.in | 1 + src/video_capture.c | 11 ++ src/video_capture/muxer.c | 239 ++++++++++++++++++++++++++++++++++++++ src/video_capture/muxer.h | 48 ++++++++ 4 files changed, 299 insertions(+) create mode 100644 src/video_capture/muxer.c create mode 100644 src/video_capture/muxer.h diff --git a/Makefile.in b/Makefile.in index 879abf0a2..7a5806cf7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -120,6 +120,7 @@ OBJS = @OBJS@ \ src/video_codec.o \ src/video_capture.o \ src/video_capture/aggregate.o \ + src/video_capture/muxer.o \ src/video_capture/import.o \ src/video_capture/null.o \ src/video_compress.o \ diff --git a/src/video_capture.c b/src/video_capture.c index 3c6d46934..468b6d3f0 100644 --- a/src/video_capture.c +++ b/src/video_capture.c @@ -81,6 +81,7 @@ #include "video_capture/testcard2.h" #include "video_capture/v4l2.h" #include "video_capture/rtsp.h" +#include "video_capture/muxer.h" #define VIDCAP_MAGIC 0x76ae98f0 @@ -303,6 +304,16 @@ struct vidcap_device_api vidcap_device_table[] = { MK_NAME(vidcap_testcard_grab), NULL }, + { + /* Mixer of many vid cap devices */ + 0, + "muxer", + MK_NAME(vidcap_muxer_probe), + MK_NAME(vidcap_muxer_init), + MK_NAME(vidcap_muxer_done), + MK_NAME(vidcap_muxer_grab), + NULL + }, #if defined HAVE_TESTCARD2 || defined BUILD_LIBRARIES { /* Dummy sender for testing purposes */ diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c new file mode 100644 index 000000000..a0234a511 --- /dev/null +++ b/src/video_capture/muxer.c @@ -0,0 +1,239 @@ +/** + * @file video_capture/muxer.c + * @author Gerard Castillo + * + * @brief Muxer of video capturers, N to 1. + */ +/* + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Fundació i2CAT nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "host.h" +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" + +#include "debug.h" +#include "video.h" +#include "video_capture.h" + +#include "tv.h" + +#include "video_capture/muxer.h" +#include "audio/audio.h" + +#include +#include + +/* prototypes of functions defined in this module */ +static void show_help(void); + +static void show_help() +{ + printf("Muxer capture\n"); + printf("Usage\n"); + printf("\t-t muxer -t -t ....]\n"); + printf("\t\twhere devn_config is a complete configuration string of device involved in the muxer device\n"); + +} + +struct vidcap_muxer_state { + struct vidcap **devices; + int devices_cnt; + + struct video_frame *frame; + int frames; + struct timeval t, t0; + + int audio_source_index; +}; + + +struct vidcap_type * +vidcap_muxer_probe(void) +{ + struct vidcap_type* vt; + + vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type)); + if (vt != NULL) { + vt->id = VIDCAP_MUXER_ID; + vt->name = "muxer"; + vt->description = "Muxer video capture"; + } + return vt; +} + +void * +vidcap_muxer_init(const struct vidcap_params *params) +{ + struct vidcap_muxer_state *s; + int i; + + printf("vidcap_muxer_init\n"); + + + s = (struct vidcap_muxer_state *) calloc(1, sizeof(struct vidcap_muxer_state)); + if(s == NULL) { + printf("Unable to allocate muxer capture state\n"); + return NULL; + } + + s->audio_source_index = -1; + s->frames = 0; + gettimeofday(&s->t0, NULL); + + if(vidcap_params_get_fmt(params) && strcmp(vidcap_params_get_fmt(params), "") != 0) { + show_help(); + return &vidcap_init_noerr; + } + + + s->devices_cnt = 0; + const struct vidcap_params *tmp = params; + while((tmp = vidcap_params_get_next(tmp))) { + if (vidcap_params_get_driver(tmp) != NULL) + s->devices_cnt++; + else + break; + } + + s->devices = calloc(s->devices_cnt, sizeof(struct vidcap *)); + i = 0; + tmp = params; + for (int i = 0; i < s->devices_cnt; ++i) { + tmp = vidcap_params_get_next(tmp); + + int ret = initialize_video_capture(NULL, tmp, &s->devices[i]); + if(ret != 0) { + fprintf(stderr, "[muxer] Unable to initialize device %d (%s:%s).\n", + i, vidcap_params_get_driver(tmp), + vidcap_params_get_fmt(tmp)); + goto error; + } + } + + s->frame = vf_alloc(s->devices_cnt); + + return s; + +error: + if(s->devices) { + int i; + for (i = 0u; i < s->devices_cnt; ++i) { + if(s->devices[i]) { + vidcap_done(s->devices[i]); + } + } + } + free(s); + return NULL; +} + +void +vidcap_muxer_done(void *state) +{ + struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; + + assert(s != NULL); + + if (s != NULL) { + int i; + for (i = 0; i < s->devices_cnt; ++i) { + vidcap_done(s->devices[i]); + } + } + + vf_free(s->frame); +} + +struct video_frame * +vidcap_muxer_grab(void *state, struct audio_frame **audio) +{ + struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; + struct audio_frame *audio_frame = NULL; + struct video_frame *frame = NULL; + + if(audio_frame) { + *audio = audio_frame; + } else { + *audio = NULL; + } + for (int i = 0; i < s->devices_cnt; ++i) { + frame = NULL; + while(!frame) { + frame = vidcap_grab(s->devices[i], &audio_frame); + } + if (i == 0) { + s->frame->color_spec = frame->color_spec; + s->frame->interlacing = frame->interlacing; + s->frame->fps = frame->fps; + } + if (s->audio_source_index == -1 && audio_frame != NULL) { + fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", + i); + s->audio_source_index = i; + } + if (s->audio_source_index == i) { + *audio = audio_frame; + } + if (frame->color_spec != s->frame->color_spec || + frame->fps != s->frame->fps || + frame->interlacing != s->frame->interlacing) { + fprintf(stderr, "[muxer] Different format detected: "); + if(frame->color_spec != s->frame->color_spec) + fprintf(stderr, "codec"); + if(frame->interlacing != s->frame->interlacing) + fprintf(stderr, "interlacing"); + if(frame->fps != s->frame->fps) + fprintf(stderr, "FPS (%.2f and %.2f)", frame->fps, s->frame->fps); + fprintf(stderr, "\n"); + + return NULL; + } + vf_get_tile(s->frame, i)->width = vf_get_tile(frame, 0)->width; + vf_get_tile(s->frame, i)->height = vf_get_tile(frame, 0)->height; + vf_get_tile(s->frame, i)->data_len = vf_get_tile(frame, 0)->data_len; + vf_get_tile(s->frame, i)->data = vf_get_tile(frame, 0)->data; + } + s->frames++; + gettimeofday(&s->t, NULL); + double seconds = tv_diff(s->t, s->t0); + if (seconds >= 5) { + float fps = s->frames / seconds; + fprintf(stderr, "[muxer cap.] %d frames in %g seconds = %g FPS\n", s->frames, seconds, fps); + s->t0 = s->t; + s->frames = 0; + } + + return s->frame; +} + diff --git a/src/video_capture/muxer.h b/src/video_capture/muxer.h new file mode 100644 index 000000000..bec48a626 --- /dev/null +++ b/src/video_capture/muxer.h @@ -0,0 +1,48 @@ +/* + * FILE: muxer.h + * AUTHORS: Gerard Castillo + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Fundació i2CAT, + * Internet I Innovació Digital a Catalunya + * + * 4. Neither the name of the CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define VIDCAP_MUXER_ID 0x9bd6abc0 //md5 hash of VIDCAP_MUXER_ID string == 241c3648599dc72ce3f119a99bd6abc0 + +struct vidcap_type *vidcap_muxer_probe(void); +void *vidcap_muxer_init(const struct vidcap_params *params); +void vidcap_muxer_done(void *state); +struct video_frame *vidcap_muxer_grab(void *state, struct audio_frame **audio); + From 3e16c52e5db1a536e1a84e3bd959b377767742fc Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 12 Sep 2013 15:03:16 +0200 Subject: [PATCH 02/57] implementating...testing if it is possible... --- src/video_capture/muxer.c | 80 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index a0234a511..0fd6db890 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -141,7 +141,7 @@ vidcap_muxer_init(const struct vidcap_params *params) } } - s->frame = vf_alloc(s->devices_cnt); + s->frame = vf_alloc(1);//s->devices_cnt); return s; @@ -175,6 +175,8 @@ vidcap_muxer_done(void *state) vf_free(s->frame); } +int icounting=0; + struct video_frame * vidcap_muxer_grab(void *state, struct audio_frame **audio) { @@ -182,56 +184,62 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) struct audio_frame *audio_frame = NULL; struct video_frame *frame = NULL; + if(audio_frame) { *audio = audio_frame; } else { *audio = NULL; } - for (int i = 0; i < s->devices_cnt; ++i) { + //for (int i = 0; i < s->devices_cnt; ++i) { frame = NULL; while(!frame) { - frame = vidcap_grab(s->devices[i], &audio_frame); + frame = vidcap_grab(s->devices[icounting], &audio_frame); } - if (i == 0) { - s->frame->color_spec = frame->color_spec; - s->frame->interlacing = frame->interlacing; - s->frame->fps = frame->fps; - } - if (s->audio_source_index == -1 && audio_frame != NULL) { - fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", - i); - s->audio_source_index = i; - } - if (s->audio_source_index == i) { - *audio = audio_frame; - } - if (frame->color_spec != s->frame->color_spec || - frame->fps != s->frame->fps || - frame->interlacing != s->frame->interlacing) { - fprintf(stderr, "[muxer] Different format detected: "); - if(frame->color_spec != s->frame->color_spec) - fprintf(stderr, "codec"); - if(frame->interlacing != s->frame->interlacing) - fprintf(stderr, "interlacing"); - if(frame->fps != s->frame->fps) - fprintf(stderr, "FPS (%.2f and %.2f)", frame->fps, s->frame->fps); - fprintf(stderr, "\n"); - - return NULL; - } - vf_get_tile(s->frame, i)->width = vf_get_tile(frame, 0)->width; - vf_get_tile(s->frame, i)->height = vf_get_tile(frame, 0)->height; - vf_get_tile(s->frame, i)->data_len = vf_get_tile(frame, 0)->data_len; - vf_get_tile(s->frame, i)->data = vf_get_tile(frame, 0)->data; - } +// if (icounting == 0) { +// s->frame->color_spec = frame->color_spec; +// s->frame->interlacing = frame->interlacing; +// s->frame->fps = frame->fps; +// } +// if (s->audio_source_index == -1 && audio_frame != NULL) { +// fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", +// icounting); +// s->audio_source_index = icounting; +// } +// if (s->audio_source_index == icounting) { +// *audio = audio_frame; +// } +// if (frame->color_spec != s->frame->color_spec || +// frame->fps != s->frame->fps || +// frame->interlacing != s->frame->interlacing) { +// fprintf(stderr, "[muxer] Different format detected: "); +// if(frame->color_spec != s->frame->color_spec) +// fprintf(stderr, "codec"); +// if(frame->interlacing != s->frame->interlacing) +// fprintf(stderr, "interlacing"); +// if(frame->fps != s->frame->fps) +// fprintf(stderr, "FPS (%.2f and %.2f)", frame->fps, s->frame->fps); +// fprintf(stderr, "\n"); +// +// //return NULL; +// } + vf_get_tile(s->frame, 0)->width = vf_get_tile(frame, 0)->width; + vf_get_tile(s->frame, 0)->height = vf_get_tile(frame, 0)->height; + vf_get_tile(s->frame, 0)->data_len = vf_get_tile(frame, 0)->data_len; + vf_get_tile(s->frame, 0)->data = vf_get_tile(frame, 0)->data; + s->frame->color_spec = frame->color_spec; + s->frame->interlacing = frame->interlacing; + s->frame->fps = 15;//frame->fps; + + //} s->frames++; gettimeofday(&s->t, NULL); double seconds = tv_diff(s->t, s->t0); if (seconds >= 5) { float fps = s->frames / seconds; - fprintf(stderr, "[muxer cap.] %d frames in %g seconds = %g FPS\n", s->frames, seconds, fps); + fprintf(stderr, "[muxer] %d frames in %g seconds = %g FPS\n", s->frames, seconds, fps); s->t0 = s->t; s->frames = 0; + icounting=(icounting+1)%s->devices_cnt; } return s->frame; From 201159a1b2d48acdbc4f13f79e47350bd326d1fa Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 13 Sep 2013 12:00:52 +0200 Subject: [PATCH 03/57] keyboard handler added --- src/video_capture/muxer.c | 273 ++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 103 deletions(-) diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index 0fd6db890..1a875cd2d 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -53,7 +53,15 @@ #include #include +#include +#include +#include +#include + +/** + * MUXER CAPTURE + */ /* prototypes of functions defined in this module */ static void show_help(void); @@ -74,6 +82,8 @@ struct vidcap_muxer_state { int frames; struct timeval t, t0; + int dev_index; + int audio_source_index; }; @@ -95,67 +105,67 @@ vidcap_muxer_probe(void) void * vidcap_muxer_init(const struct vidcap_params *params) { - struct vidcap_muxer_state *s; - int i; + struct vidcap_muxer_state *s; + int i; - printf("vidcap_muxer_init\n"); + printf("vidcap_muxer_init\n"); - - s = (struct vidcap_muxer_state *) calloc(1, sizeof(struct vidcap_muxer_state)); - if(s == NULL) { - printf("Unable to allocate muxer capture state\n"); - return NULL; - } - - s->audio_source_index = -1; - s->frames = 0; - gettimeofday(&s->t0, NULL); - - if(vidcap_params_get_fmt(params) && strcmp(vidcap_params_get_fmt(params), "") != 0) { - show_help(); - return &vidcap_init_noerr; - } - - - s->devices_cnt = 0; - const struct vidcap_params *tmp = params; - while((tmp = vidcap_params_get_next(tmp))) { - if (vidcap_params_get_driver(tmp) != NULL) - s->devices_cnt++; - else - break; - } - - s->devices = calloc(s->devices_cnt, sizeof(struct vidcap *)); - i = 0; - tmp = params; - for (int i = 0; i < s->devices_cnt; ++i) { - tmp = vidcap_params_get_next(tmp); - - int ret = initialize_video_capture(NULL, tmp, &s->devices[i]); - if(ret != 0) { - fprintf(stderr, "[muxer] Unable to initialize device %d (%s:%s).\n", - i, vidcap_params_get_driver(tmp), - vidcap_params_get_fmt(tmp)); - goto error; - } - } - - s->frame = vf_alloc(1);//s->devices_cnt); - - return s; - -error: - if(s->devices) { - int i; - for (i = 0u; i < s->devices_cnt; ++i) { - if(s->devices[i]) { - vidcap_done(s->devices[i]); - } - } - } - free(s); + s = (struct vidcap_muxer_state *) calloc(1, + sizeof(struct vidcap_muxer_state)); + if (s == NULL) { + printf("Unable to allocate muxer capture state\n"); return NULL; + } + + s->audio_source_index = -1; + s->frames = 0; + s->dev_index = 0; + gettimeofday(&s->t0, NULL); + + if (vidcap_params_get_fmt(params) + && strcmp(vidcap_params_get_fmt(params), "") != 0) + { + show_help(); + return &vidcap_init_noerr; + } + + s->devices_cnt = 0; + const struct vidcap_params *tmp = params; + while ((tmp = vidcap_params_get_next(tmp))) { + if (vidcap_params_get_driver(tmp) != NULL) + s->devices_cnt++; + else + break; + } + + s->devices = calloc(s->devices_cnt, sizeof(struct vidcap *)); + i = 0; + tmp = params; + for (int i = 0; i < s->devices_cnt; ++i) { + tmp = vidcap_params_get_next(tmp); + + int ret = initialize_video_capture(NULL, tmp, &s->devices[i]); + if (ret != 0) { + fprintf(stderr, "[muxer] Unable to initialize device %d (%s:%s).\n", + i, vidcap_params_get_driver(tmp), vidcap_params_get_fmt(tmp)); + goto error; + } + } + + s->frame = vf_alloc(1); //s->devices_cnt); + + return s; + + error: if (s->devices) { + int i; + for (i = 0u; i < s->devices_cnt; ++i) { + if (s->devices[i]) { + vidcap_done(s->devices[i]); + } + } + } + free(s); + return NULL; } void @@ -175,39 +185,45 @@ vidcap_muxer_done(void *state) vf_free(s->frame); } -int icounting=0; - struct video_frame * vidcap_muxer_grab(void *state, struct audio_frame **audio) { struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; - struct audio_frame *audio_frame = NULL; - struct video_frame *frame = NULL; + struct audio_frame *audio_frame = NULL; + struct video_frame *frame = NULL; + + set_conio_terminal_mode(); + int c; + + if (kbhit()) { + c = (int) getch(); + debug_msg("num %d pressed...\r\n", c); + } + if(c >= 48 && c < 48+s->devices_cnt){ + s->dev_index = c - 48; + printf("[muxer] device %d selected of %d devices...\r\n",s->dev_index,s->devices_cnt); + } + reset_terminal_mode(); - if(audio_frame) { - *audio = audio_frame; - } else { - *audio = NULL; - } - //for (int i = 0; i < s->devices_cnt; ++i) { - frame = NULL; - while(!frame) { - frame = vidcap_grab(s->devices[icounting], &audio_frame); - } -// if (icounting == 0) { -// s->frame->color_spec = frame->color_spec; -// s->frame->interlacing = frame->interlacing; -// s->frame->fps = frame->fps; -// } -// if (s->audio_source_index == -1 && audio_frame != NULL) { -// fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", -// icounting); -// s->audio_source_index = icounting; -// } -// if (s->audio_source_index == icounting) { -// *audio = audio_frame; -// } + if (audio_frame) { + *audio = audio_frame; + } else { + *audio = NULL; + } + + frame = NULL; + while (!frame) { + frame = vidcap_grab(s->devices[s->dev_index], &audio_frame); + } + if (s->audio_source_index == -1 && audio_frame != NULL) { + fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", + s->dev_index); + s->audio_source_index = s->dev_index; + } + if (s->audio_source_index == s->dev_index) { + *audio = audio_frame; + } // if (frame->color_spec != s->frame->color_spec || // frame->fps != s->frame->fps || // frame->interlacing != s->frame->interlacing) { @@ -222,26 +238,77 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) // // //return NULL; // } - vf_get_tile(s->frame, 0)->width = vf_get_tile(frame, 0)->width; - vf_get_tile(s->frame, 0)->height = vf_get_tile(frame, 0)->height; - vf_get_tile(s->frame, 0)->data_len = vf_get_tile(frame, 0)->data_len; - vf_get_tile(s->frame, 0)->data = vf_get_tile(frame, 0)->data; - s->frame->color_spec = frame->color_spec; - s->frame->interlacing = frame->interlacing; - s->frame->fps = 15;//frame->fps; + if (frame != NULL) { + vf_get_tile(s->frame, 0)->width = vf_get_tile(frame, 0)->width; + vf_get_tile(s->frame, 0)->height = vf_get_tile(frame, 0)->height; + vf_get_tile(s->frame, 0)->data_len = vf_get_tile(frame, 0)->data_len; + vf_get_tile(s->frame, 0)->data = vf_get_tile(frame, 0)->data; + s->frame->color_spec = frame->color_spec; + s->frame->interlacing = frame->interlacing; + if (frame->fps == 0) + s->frame->fps = 15; + else + s->frame->fps = frame->fps; + } else + return NULL; - //} - s->frames++; - gettimeofday(&s->t, NULL); - double seconds = tv_diff(s->t, s->t0); - if (seconds >= 5) { - float fps = s->frames / seconds; - fprintf(stderr, "[muxer] %d frames in %g seconds = %g FPS\n", s->frames, seconds, fps); - s->t0 = s->t; - s->frames = 0; - icounting=(icounting+1)%s->devices_cnt; - } + s->frames++; + gettimeofday(&s->t, NULL); + double seconds = tv_diff(s->t, s->t0); + if (seconds >= 5) { + float fps = s->frames / seconds; + fprintf(stderr, "[muxer] %d frames in %g seconds = %g FPS\n", s->frames, + seconds, fps); + s->t0 = s->t; + s->frames = 0; + //s->dev_index = (s->dev_index + 1) % s->devices_cnt; + } return s->frame; } +/** + * KEYBOARD HANDLER + */ + +struct termios orig_termios; + +void reset_terminal_mode() +{ + tcsetattr(0, TCSANOW, &orig_termios); +} + +void set_conio_terminal_mode() +{ + struct termios new_termios; + + /* take two copies - one for now, one for later */ + tcgetattr(0, &orig_termios); + memcpy(&new_termios, &orig_termios, sizeof(new_termios)); + + /* register cleanup handler, and set the new terminal mode */ + atexit(reset_terminal_mode); + cfmakeraw(&new_termios); + tcsetattr(0, TCSANOW, &new_termios); +} + +int kbhit() +{ + struct timeval tv = { 0L, 0L }; + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return select(1, &fds, NULL, NULL, &tv); +} + +int getch() +{ + int r; + unsigned char c; + if ((r = read(0, &c, sizeof(c))) < 0) { + return r; + } else { + return c; + } +} + From 661c8faf02acc28020769c639b818ba59245be84 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 26 Sep 2013 14:57:34 +0200 Subject: [PATCH 04/57] rtsp improvements --- src/video_capture/muxer.c | 20 +++--- src/video_capture/rtsp.c | 144 +++++++++++++++++++++----------------- src/video_capture/rtsp.h | 3 +- 3 files changed, 92 insertions(+), 75 deletions(-) diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index 1a875cd2d..6e507a322 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -79,6 +79,7 @@ struct vidcap_muxer_state { int devices_cnt; struct video_frame *frame; + struct video_frame *prev_frame; int frames; struct timeval t, t0; @@ -152,7 +153,7 @@ vidcap_muxer_init(const struct vidcap_params *params) } } - s->frame = vf_alloc(1); //s->devices_cnt); + s->frame = vf_alloc(1); return s; @@ -192,9 +193,11 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) struct audio_frame *audio_frame = NULL; struct video_frame *frame = NULL; + /** + * remote control (now keyboard handler) + */ set_conio_terminal_mode(); int c; - if (kbhit()) { c = (int) getch(); debug_msg("num %d pressed...\r\n", c); @@ -205,17 +208,17 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) } reset_terminal_mode(); - + /** + * vidcap_grap + */ + while (!frame) { + frame = vidcap_grab(s->devices[s->dev_index], &audio_frame); + } if (audio_frame) { *audio = audio_frame; } else { *audio = NULL; } - - frame = NULL; - while (!frame) { - frame = vidcap_grab(s->devices[s->dev_index], &audio_frame); - } if (s->audio_source_index == -1 && audio_frame != NULL) { fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", s->dev_index); @@ -261,7 +264,6 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) seconds, fps); s->t0 = s->t; s->frames = 0; - //s->dev_index = (s->dev_index + 1) % s->devices_cnt; } return s->frame; diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index b28ccd1ce..facbb5c32 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -90,13 +90,15 @@ struct recieved_data { /* error handling macros */ #define my_curl_easy_setopt(A, B, C) \ if ((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK){ \ -fprintf(stderr, "curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ +fprintf(stderr, "[rtsp error] curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ +printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ exit(0); \ } #define my_curl_easy_perform(A) \ if ((res = curl_easy_perform((A))) != CURLE_OK){ \ -fprintf(stderr, "curl_easy_perform(%s) failed: %d\n", #A, res); \ +fprintf(stderr, "[rtsp error] curl_easy_perform(%s) failed: %d\n", #A, res); \ +printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ exit(0); \ } @@ -147,6 +149,7 @@ init_decompressor(void *state); static void * vidcap_rtsp_thread(void *args); + static void show_help(void); @@ -224,6 +227,18 @@ show_help() { "\t\t receiver decompress boolean [true|false] - default: false - no decompression active\n\n"); } +void +rtsp_keepalive(void *state) { + struct rtsp_state *s; + s = (struct rtsp_state *) state; + struct timeval now; + gettimeofday(&now, NULL); + if (tv_diff(now, s->prev_time) >= 30) { + rtsp_get_parameters(s->curl, s->uri); + gettimeofday(&s->prev_time, NULL); + } +} + static void * vidcap_rtsp_thread(void *arg) { struct rtsp_state *s; @@ -236,10 +251,7 @@ vidcap_rtsp_thread(void *arg) { gettimeofday(&s->curr_time, NULL); s->timestamp = tv_diff(s->curr_time, s->start_time) * 90000; - if (tv_diff(s->curr_time, s->prev_time) >= 30) { - rtsp_get_parameters(s->curl, s->uri); - gettimeofday(&s->prev_time, NULL); - } + rtsp_keepalive(s); rtp_update(s->device, s->curr_time); //TODO rtcp communication between ug and rtsp server? @@ -258,19 +270,20 @@ vidcap_rtsp_thread(void *arg) { if (pbuf_decode(s->cp->playout_buffer, s->curr_time, decode_frame_h264, s->rx_data)) { - pthread_mutex_lock(&s->lock); - { - while (s->new_frame && !s->should_exit) { - s->worker_waiting = true; - pthread_cond_wait(&s->worker_cv, &s->lock); - s->worker_waiting = false; - } - s->new_frame = true; + if(pthread_mutex_trylock(&s->lock)==0){ + { + while (s->new_frame && !s->should_exit) { + s->worker_waiting = true; + pthread_cond_wait(&s->worker_cv, &s->lock); + s->worker_waiting = false; + } + s->new_frame = true; - if (s->boss_waiting) - pthread_cond_signal(&s->boss_cv); + if (s->boss_waiting) + pthread_cond_signal(&s->boss_cv); + } + pthread_mutex_unlock(&s->lock); } - pthread_mutex_unlock(&s->lock); } pbuf_remove(s->cp->playout_buffer, s->curr_time); s->cp = pdb_iter_next(&it); @@ -288,58 +301,59 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { *audio = NULL; - pthread_mutex_lock(&s->lock); - { - while (!s->new_frame) { - s->boss_waiting = true; - pthread_cond_wait(&s->boss_cv, &s->lock); - s->boss_waiting = false; + if(pthread_mutex_trylock(&s->lock)==0){ + { + while (!s->new_frame) { + s->boss_waiting = true; + pthread_cond_wait(&s->boss_cv, &s->lock); + s->boss_waiting = false; + } + + gettimeofday(&s->curr_time, NULL); + + s->frame->tiles[0].data_len = s->rx_data->buffer_len; + + memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, + s->rx_data->buffer_len); + + memcpy(s->frame->tiles[0].data, s->data, + s->rx_data->buffer_len + s->nals_size); + s->frame->tiles[0].data_len += s->nals_size; + + if (s->decompress) { + decompress_frame(s->sd, (unsigned char *) s->out_frame, + (unsigned char *) s->frame->tiles[0].data, + s->rx_data->buffer_len + s->nals_size, 0); + s->frame->tiles[0].data = s->out_frame; //TODO memcpy? + s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) + * s->des.height; //TODO reconfigurable + } + s->new_frame = false; + + if (s->worker_waiting) { + pthread_cond_signal(&s->worker_cv); + } } + pthread_mutex_unlock(&s->lock); - gettimeofday(&s->curr_time, NULL); - - s->frame->tiles[0].data_len = s->rx_data->buffer_len; - - memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, - s->rx_data->buffer_len); - - memcpy(s->frame->tiles[0].data, s->data, - s->rx_data->buffer_len + s->nals_size); - s->frame->tiles[0].data_len += s->nals_size; - - if (s->decompress) { - decompress_frame(s->sd, (unsigned char *) s->out_frame, - (unsigned char *) s->frame->tiles[0].data, - s->rx_data->buffer_len + s->nals_size, 0); - s->frame->tiles[0].data = s->out_frame; //TODO memcpy? - s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) - * s->des.height; //TODO reconfigurable - } - s->new_frame = false; - - if (s->worker_waiting) { - pthread_cond_signal(&s->worker_cv); + gettimeofday(&s->t, NULL); + double seconds = tv_diff(s->t, s->t0); + if (seconds >= 5) { + float fps = s->frames / seconds; + fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", + s->frames, seconds, fps); + s->t0 = s->t; + s->frames = 0; + //Threshold of 1fps in order to update fps parameter + if (fps > s->fps + 1 || fps < s->fps - 1) { + debug_msg( + "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); + s->frame->fps = fps; + s->fps = fps; + } } + s->frames++; } - pthread_mutex_unlock(&s->lock); - - gettimeofday(&s->t, NULL); - double seconds = tv_diff(s->t, s->t0); - if (seconds >= 5) { - float fps = s->frames / seconds; - fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", - s->frames, seconds, fps); - s->t0 = s->t; - s->frames = 0; - //Threshold of 1fps in order to update fps parameter - if (fps > s->fps + 1 || fps < s->fps - 1) { - debug_msg( - "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); - s->frame->fps = fps; - s->fps = fps; - } - } - s->frames++; return s->frame; } diff --git a/src/video_capture/rtsp.h b/src/video_capture/rtsp.h index d018c90e4..8ef5d4239 100644 --- a/src/video_capture/rtsp.h +++ b/src/video_capture/rtsp.h @@ -48,7 +48,8 @@ extern "C" { vidcap_rtsp_done(void *state); struct video_frame * vidcap_rtsp_grab(void *state, struct audio_frame **audio); - + void + rtsp_keepalive(void *state); #endif #ifdef __cplusplus From 18141ecd0b2a33a2a8a7bbb8189299e42d07d5ba Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Wed, 2 Oct 2013 14:22:21 +0200 Subject: [PATCH 05/57] improvement: robust rtsp threading --- src/video_capture/rtsp.c | 35 ++++++++++++++++++++++------------- src/video_capture/rtsp.h | 2 -- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index facbb5c32..19f6820da 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -153,6 +153,9 @@ vidcap_rtsp_thread(void *args); static void show_help(void); +void +rtsp_keepalive(void *state); + FILE *F_video_rtsp = NULL; /** * @struct rtsp_state @@ -173,9 +176,8 @@ struct rtsp_state { struct recieved_data *rx_data; bool new_frame; - bool pbuf_removed; - bool decompress; + bool grab; struct rtp *device; struct pdb *participants; @@ -233,7 +235,7 @@ rtsp_keepalive(void *state) { s = (struct rtsp_state *) state; struct timeval now; gettimeofday(&now, NULL); - if (tv_diff(now, s->prev_time) >= 30) { + if (tv_diff(now, s->prev_time) >= 20) { rtsp_get_parameters(s->curl, s->uri); gettimeofday(&s->prev_time, NULL); } @@ -264,30 +266,32 @@ vidcap_rtsp_thread(void *arg) { pdb_iter_t it; s->cp = pdb_iter_init(s->participants, &it); - s->pbuf_removed = true; - while (s->cp != NULL) { - if (pbuf_decode(s->cp->playout_buffer, s->curr_time, - decode_frame_h264, s->rx_data)) - { - if(pthread_mutex_trylock(&s->lock)==0){ - { + if (pthread_mutex_trylock(&s->lock) == 0) { + { + if(s->grab){ + while (s->new_frame && !s->should_exit) { s->worker_waiting = true; pthread_cond_wait(&s->worker_cv, &s->lock); s->worker_waiting = false; } - s->new_frame = true; + if (pbuf_decode(s->cp->playout_buffer, s->curr_time, + decode_frame_h264, s->rx_data)) + { + s->new_frame = true; + } if (s->boss_waiting) pthread_cond_signal(&s->boss_cv); } - pthread_mutex_unlock(&s->lock); } + pthread_mutex_unlock(&s->lock); } pbuf_remove(s->cp->playout_buffer, s->curr_time); s->cp = pdb_iter_next(&it); } + pdb_iter_done(&it); } } @@ -303,6 +307,8 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { if(pthread_mutex_trylock(&s->lock)==0){ { + s->grab = true; + while (!s->new_frame) { s->boss_waiting = true; pthread_cond_wait(&s->boss_cv, &s->lock); @@ -326,7 +332,7 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { s->rx_data->buffer_len + s->nals_size, 0); s->frame->tiles[0].data = s->out_frame; //TODO memcpy? s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) - * s->des.height; //TODO reconfigurable + * s->des.height; //TODO reconfigurable? } s->new_frame = false; @@ -353,6 +359,8 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { } } s->frames++; + s->grab = false; + } return s->frame; @@ -372,6 +380,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { gettimeofday(&s->t0, NULL); s->frames = 0; s->nals = malloc(1024); + s->grab = false; s->addr = "127.0.0.1"; s->device = NULL; diff --git a/src/video_capture/rtsp.h b/src/video_capture/rtsp.h index 8ef5d4239..5fc55ce22 100644 --- a/src/video_capture/rtsp.h +++ b/src/video_capture/rtsp.h @@ -48,8 +48,6 @@ extern "C" { vidcap_rtsp_done(void *state); struct video_frame * vidcap_rtsp_grab(void *state, struct audio_frame **audio); - void - rtsp_keepalive(void *state); #endif #ifdef __cplusplus From fd90580191c6206d796f24f1a54cdd51e507f23d Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 10 Oct 2013 12:41:29 +0200 Subject: [PATCH 06/57] improve header dependencies, and intra and before frames detection --- src/rtp/rtpdec_h264.c | 221 ++++++++++++++++++++------------------- src/rtp/rtpdec_h264.h | 8 ++ src/video_capture/rtsp.c | 24 ++--- src/video_capture/rtsp.h | 2 + 4 files changed, 133 insertions(+), 122 deletions(-) diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index 00170b522..43821c74c 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -40,7 +40,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ - #ifdef HAVE_CONFIG_H #include "config.h" #include "config_unix.h" @@ -49,26 +48,19 @@ #include "perf.h" #include "rtp/rtp.h" #include "rtp/rtp_callback.h" -//#include "rtp/rtpdec_h264.h" -#include "video_capture/rtsp.h" #include "rtp/pbuf.h" +#include "rtp/rtpdec_h264.h" -struct recieved_data { - uint32_t buffer_len; //[MAX_SUBSTREAMS]; - //uint32_t buffer_num;//[MAX_SUBSTREAMS]; - char *frame_buffer; //[MAX_SUBSTREAMS]; -}; static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; -int -decode_frame_h264(struct coded_data *cdata, void *rx_data); -int -decode_frame_h264(struct coded_data *cdata, void *rx_data) { +int decode_frame_h264(struct coded_data *cdata, void *rx_data) { rtp_packet *pckt = NULL; + int substream = 0; struct coded_data *orig = cdata; uint8_t nal; uint8_t type; + uint8_t nri; int pass; int total_length = 0; @@ -84,6 +76,8 @@ decode_frame_h264(struct coded_data *cdata, void *rx_data) { cdata = orig; buffers->buffer_len = total_length; dst = buffers->frame_buffer + total_length; + buffers->bframe = TRUE; + buffers->iframe = FALSE; } while (cdata != NULL) { @@ -96,121 +90,138 @@ decode_frame_h264(struct coded_data *cdata, void *rx_data) { nal = (uint8_t) pckt->data[0]; type = nal & 0x1f; + nri = nal & 0x60; if (type >= 1 && type <= 23) { + if (buffers->bframe && !(type == 1 && nri == 0)){ + buffers->bframe = FALSE; + } + if (!buffers->iframe && type == 5 ){ + buffers->iframe =TRUE; + } type = 1; } const uint8_t *src = NULL; switch (type) { - case 0: - case 1: - if (pass == 0) { - debug_msg("NAL type 1\n"); - total_length += sizeof(start_sequence) + pckt->data_len; - } else { - dst -= pckt->data_len + sizeof(start_sequence); - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), pckt->data, pckt->data_len); - unsigned char *dst2 = (unsigned char *)dst; - } - break; - case 24: - src = (const uint8_t *) pckt->data; - src_len = pckt->data_len; + case 0: + case 1: + if (pass == 0) { + debug_msg("NAL type 1\n"); + total_length += sizeof(start_sequence) + pckt->data_len; + } else { + dst -= pckt->data_len + sizeof(start_sequence); + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), pckt->data, pckt->data_len); + unsigned char *dst2 = (unsigned char *)dst; + } + break; + case 24: + src = (const uint8_t *) pckt->data; + src_len = pckt->data_len; - src++; - src_len--; + src++; + src_len--; - while (src_len > 2) { - //TODO: Not properly tested - uint16_t nal_size; - memcpy(&nal_size, src, sizeof(uint16_t)); + while (src_len > 2) { + //TODO: Not properly tested + //TODO: bframes and iframes detection + uint16_t nal_size; + memcpy(&nal_size, src, sizeof(uint16_t)); - src += 2; - src_len -= 2; - - if (nal_size <= src_len) { - if (pass == 0) { - total_length += sizeof(start_sequence) + nal_size; - } else { - dst -= nal_size + sizeof(start_sequence); - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), src, nal_size); - } - } else { - error_msg("NAL size exceeds length: %u %d\n", nal_size, src_len); - return FALSE; - } - src += nal_size; - src_len -= nal_size; - - if (src_len < 0) { - error_msg("Consumed more bytes than we got! (%d)\n", src_len); - return FALSE; - } - } - break; - - case 25: - case 26: - case 27: - case 29: - error_msg("Unhandled NAL type\n"); - return FALSE; - case 28: - src = (const uint8_t *) pckt->data; - src_len = pckt->data_len; - - src++; - src_len--; - - if (src_len > 1) { - uint8_t fu_header = *src; - uint8_t start_bit = fu_header >> 7; - //uint8_t end_bit = (fu_header & 0x40) >> 6; - uint8_t nal_type = fu_header & 0x1f; - uint8_t reconstructed_nal; - - // Reconstruct this packet's true nal; only the data follows. - /* The original nal forbidden bit and NRI are stored in this - * packet's nal. */ - reconstructed_nal = nal & 0xe0; - reconstructed_nal |= nal_type; - - // skip the fu_header - src++; - src_len--; + src += 2; + src_len -= 2; + if (nal_size <= src_len) { if (pass == 0) { - if (start_bit) { - total_length += sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; - } else { - total_length += src_len; - } + total_length += sizeof(start_sequence) + nal_size; } else { - if (start_bit) { - dst -= sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), &reconstructed_nal, sizeof(reconstructed_nal)); - memcpy(dst + sizeof(start_sequence) + sizeof(reconstructed_nal), src, src_len); - } else { - dst -= src_len; - memcpy(dst, src, src_len); - } + dst -= nal_size + sizeof(start_sequence); + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), src, nal_size); } } else { - error_msg("Too short data for FU-A H264 RTP packet\n"); + error_msg("NAL size exceeds length: %u %d\n", nal_size, src_len); return FALSE; } - break; - default: - error_msg("Unknown NAL type\n"); + src += nal_size; + src_len -= nal_size; + + if (src_len < 0) { + error_msg("Consumed more bytes than we got! (%d)\n", src_len); + return FALSE; + } + } + break; + + case 25: + case 26: + case 27: + case 29: + error_msg("Unhandled NAL type\n"); + return FALSE; + case 28: + src = (const uint8_t *) pckt->data; + src_len = pckt->data_len; + + src++; + src_len--; + + if (src_len > 1) { + uint8_t fu_header = *src; + uint8_t start_bit = fu_header >> 7; + //uint8_t end_bit = (fu_header & 0x40) >> 6; + uint8_t nal_type = fu_header & 0x1f; + uint8_t reconstructed_nal; + + if (buffers->bframe && !(nal_type == 1 && nri == 0)){ + buffers->bframe = FALSE; + } + + if (!buffers->iframe && nal_type == 5){ + buffers->iframe = TRUE; + } + + // Reconstruct this packet's true nal; only the data follows. + /* The original nal forbidden bit and NRI are stored in this + * packet's nal. */ + reconstructed_nal = nal & 0xe0; + reconstructed_nal |= nal_type; + + // skip the fu_header + src++; + src_len--; + + if (pass == 0) { + if (start_bit) { + total_length += sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; + } else { + total_length += src_len; + } + } else { + if (start_bit) { + dst -= sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), &reconstructed_nal, sizeof(reconstructed_nal)); + memcpy(dst + sizeof(start_sequence) + sizeof(reconstructed_nal), src, src_len); + } else { + dst -= src_len; + memcpy(dst, src, src_len); + } + } + } else { + error_msg("Too short data for FU-A H264 RTP packet\n"); return FALSE; } + break; + default: + error_msg("Unknown NAL type\n"); + return FALSE; + } cdata = cdata->nxt; } } + return TRUE; } diff --git a/src/rtp/rtpdec_h264.h b/src/rtp/rtpdec_h264.h index be59eac81..7c101111d 100644 --- a/src/rtp/rtpdec_h264.h +++ b/src/rtp/rtpdec_h264.h @@ -44,6 +44,14 @@ #ifndef _RTP_DEC_H264_H #define _RTP_DEC_H264_H +struct recieved_data { + uint32_t buffer_len; //[MAX_SUBSTREAMS]; + //uint32_t buffer_num;//[MAX_SUBSTREAMS]; + char *frame_buffer; //[MAX_SUBSTREAMS]; + uint8_t bframe; + uint8_t iframe; +}; + int decode_frame_h264(struct coded_data *cdata, void *rx_data); diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 19f6820da..800ef65ac 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -52,8 +52,6 @@ #include #include -struct coded_data; - #include "debug.h" #include "host.h" #include "tv.h" @@ -71,21 +69,14 @@ struct coded_data; #include "video_codec.h" #include "video_capture.h" #include "video_capture/rtsp.h" -//#include "audio/audio.h" +#include "audio/audio.h" #include #define VERSION_STR "V1.0" -//TODO set lower initial video recv buffer size (to find the minimal) +//TODO set lower initial video recv buffer size (to find the minimal?) #define INITIAL_VIDEO_RECV_BUFFER_SIZE ((0.1*1920*1080)*110/100) //command line net.core setup: sysctl -w net.core.rmem_max=9123840 -//#define MAX_SUBSTREAMS 1 - -struct recieved_data { - uint32_t buffer_len; //[MAX_SUBSTREAMS]; - //uint32_t buffer_num;//[MAX_SUBSTREAMS]; - char *frame_buffer; //[MAX_SUBSTREAMS]; -}; /* error handling macros */ #define my_curl_easy_setopt(A, B, C) \ @@ -170,7 +161,7 @@ struct rtsp_state { int frames; struct video_frame *frame; struct tile *tile; -// struct audio_frame audio; + struct audio_frame audio; int width; int height; @@ -193,10 +184,10 @@ struct rtsp_state { int required_connections; uint32_t timestamp; -// int play_audio_frame; + int play_audio_frame; -// struct timeval last_audio_time; -// unsigned int grab_audio:1; + struct timeval last_audio_time; + unsigned int grab_audio:1; pthread_t rtsp_thread_id; //the worker_id pthread_mutex_t lock; @@ -256,7 +247,7 @@ vidcap_rtsp_thread(void *arg) { rtsp_keepalive(s); rtp_update(s->device, s->curr_time); - //TODO rtcp communication between ug and rtsp server? + //TODO no need of rtcp communication between ug and rtsp server? //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); s->timeout.tv_sec = 0; @@ -360,7 +351,6 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { } s->frames++; s->grab = false; - } return s->frame; diff --git a/src/video_capture/rtsp.h b/src/video_capture/rtsp.h index 5fc55ce22..7fde29818 100644 --- a/src/video_capture/rtsp.h +++ b/src/video_capture/rtsp.h @@ -39,6 +39,8 @@ extern "C" { #endif +struct audio_frame; + #define VIDCAP_RTSP_ID 0x45b3d828 //md5 hash of VIDCAP_RTSP_ID string == a208d26f519a2664a48781c845b3d828 struct vidcap_type * vidcap_rtsp_probe(void); From 21e62d2c64d2ed49aae1682683d39d1ef9394901 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 11 Oct 2013 14:05:50 +0200 Subject: [PATCH 07/57] muxer switch wait for iframe; rtsp fps parameter fix to 30fps, performs better --- src/main.c | 2 +- src/rtp/rtpdec_h264.c | 2 +- src/rtp/rtpdec_h264.h | 2 +- src/types.h | 7 ++++++ src/video_capture/muxer.c | 45 +++++++++++++++++++++++++++++++-------- src/video_capture/muxer.h | 24 +++++++++++++++++---- src/video_capture/rtsp.c | 30 ++++++++++++++------------ src/video_capture/rtsp.h | 18 +++++++++------- 8 files changed, 92 insertions(+), 38 deletions(-) diff --git a/src/main.c b/src/main.c index 44722e053..0c075aedc 100644 --- a/src/main.c +++ b/src/main.c @@ -1422,7 +1422,7 @@ int main(int argc, char *argv[]) packet_rate = 0; } - if ((h264_rtp.tx = tx_init(&root_mod, + if ((h264_rtp.tx = tx_init_h264(&root_mod, uv->requested_mtu, TX_MEDIA_VIDEO, NULL, NULL)) == NULL) { diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index 43821c74c..0b5731b55 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -68,7 +68,7 @@ int decode_frame_h264(struct coded_data *cdata, void *rx_data) { char *dst = NULL; int src_len; - struct recieved_data *buffers = (struct recieved_data *) rx_data; + struct std_frame_received *buffers = (struct std_frame_received *) rx_data; for (pass = 0; pass < 2; pass++) { diff --git a/src/rtp/rtpdec_h264.h b/src/rtp/rtpdec_h264.h index 7c101111d..61b7c6352 100644 --- a/src/rtp/rtpdec_h264.h +++ b/src/rtp/rtpdec_h264.h @@ -44,7 +44,7 @@ #ifndef _RTP_DEC_H264_H #define _RTP_DEC_H264_H -struct recieved_data { +struct std_frame_received { uint32_t buffer_len; //[MAX_SUBSTREAMS]; //uint32_t buffer_num;//[MAX_SUBSTREAMS]; char *frame_buffer; //[MAX_SUBSTREAMS]; diff --git a/src/types.h b/src/types.h index d48d56b6d..0a0972dbe 100644 --- a/src/types.h +++ b/src/types.h @@ -153,6 +153,13 @@ struct video_frame { */ void (*data_deleter)(struct video_frame *); /// @} + + //h264_params + uint8_t isStd; + uint8_t h264_bframe; + uint8_t h264_iframe; + int h264_width; + int h264_height; }; /** diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index 6e507a322..aa37bf575 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -83,7 +83,8 @@ struct vidcap_muxer_state { int frames; struct timeval t, t0; - int dev_index; + int dev_index_curr; + int dev_index_next; int audio_source_index; }; @@ -120,7 +121,9 @@ vidcap_muxer_init(const struct vidcap_params *params) s->audio_source_index = -1; s->frames = 0; - s->dev_index = 0; + s->dev_index_curr = 0; + s->dev_index_next = 0; + gettimeofday(&s->t0, NULL); if (vidcap_params_get_fmt(params) @@ -191,6 +194,8 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) { struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; struct audio_frame *audio_frame = NULL; + struct video_frame *frame_curr = NULL; + struct video_frame *frame_next = NULL; struct video_frame *frame = NULL; /** @@ -203,17 +208,39 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) debug_msg("num %d pressed...\r\n", c); } if(c >= 48 && c < 48+s->devices_cnt){ - s->dev_index = c - 48; - printf("[muxer] device %d selected of %d devices...\r\n",s->dev_index,s->devices_cnt); + // s->dev_index_curr = s->dev_index_next; + s->dev_index_next = c - 48; + printf("\n[MUXER] device %d (previous was: %d) selected of %d devices...\r\n",s->dev_index_next,s->dev_index_curr,s->devices_cnt); } reset_terminal_mode(); /** * vidcap_grap */ - while (!frame) { - frame = vidcap_grab(s->devices[s->dev_index], &audio_frame); + while (!frame_curr) { + frame_curr = vidcap_grab(s->devices[s->dev_index_curr], &audio_frame); } + if(s->dev_index_next != s->dev_index_curr){ + while (!frame_next) { + frame_next = vidcap_grab(s->devices[s->dev_index_next], &audio_frame); + } + + printf("\n\n[MUXER] frameNext is std = %d...\n\n",frame_next->isStd); + + if(frame_next->isStd == TRUE){ + printf("\n\n[MUXER] RTSP INCOMING FRAME...\n"); + if(frame_next->h264_iframe == TRUE){ + s->dev_index_curr = s->dev_index_next; + frame_curr = frame_next; + printf("[MUXER] GOT INTRA FRAME! SWITCHING...\n\n"); + }else printf("[MUXER] NO INTRA FRAME YET...\n"); + }else{ + frame_curr = frame_next; + s->dev_index_curr = s->dev_index_next; + } + } + frame = frame_curr; + if (audio_frame) { *audio = audio_frame; } else { @@ -221,10 +248,10 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) } if (s->audio_source_index == -1 && audio_frame != NULL) { fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", - s->dev_index); - s->audio_source_index = s->dev_index; + s->dev_index_curr); + s->audio_source_index = s->dev_index_curr; } - if (s->audio_source_index == s->dev_index) { + if (s->audio_source_index == s->dev_index_curr) { *audio = audio_frame; } // if (frame->color_spec != s->frame->color_spec || diff --git a/src/video_capture/muxer.h b/src/video_capture/muxer.h index bec48a626..0a743b971 100644 --- a/src/video_capture/muxer.h +++ b/src/video_capture/muxer.h @@ -39,10 +39,26 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +#ifndef _MUXER_H_ +#define _MUXER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + #define VIDCAP_MUXER_ID 0x9bd6abc0 //md5 hash of VIDCAP_MUXER_ID string == 241c3648599dc72ce3f119a99bd6abc0 -struct vidcap_type *vidcap_muxer_probe(void); -void *vidcap_muxer_init(const struct vidcap_params *params); -void vidcap_muxer_done(void *state); -struct video_frame *vidcap_muxer_grab(void *state, struct audio_frame **audio); +struct vidcap_type * +vidcap_muxer_probe(void); +void * +vidcap_muxer_init(const struct vidcap_params *params); +void +vidcap_muxer_done(void *state); +struct video_frame * +vidcap_muxer_grab(void *state, struct audio_frame **audio); +#endif + +#ifdef __cplusplus +} // END extern "C" +#endif diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 800ef65ac..7543d4668 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -165,7 +165,7 @@ struct rtsp_state { int width; int height; - struct recieved_data *rx_data; + struct std_frame_received *rx_data; bool new_frame; bool decompress; bool grab; @@ -307,12 +307,11 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { } gettimeofday(&s->curr_time, NULL); - + s->frame->h264_iframe = s->rx_data->iframe; + s->frame->h264_iframe = s->rx_data->iframe; s->frame->tiles[0].data_len = s->rx_data->buffer_len; - memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, s->rx_data->buffer_len); - memcpy(s->frame->tiles[0].data, s->data, s->rx_data->buffer_len + s->nals_size); s->frame->tiles[0].data_len += s->nals_size; @@ -341,13 +340,13 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { s->frames, seconds, fps); s->t0 = s->t; s->frames = 0; - //Threshold of 1fps in order to update fps parameter - if (fps > s->fps + 1 || fps < s->fps - 1) { - debug_msg( - "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); - s->frame->fps = fps; - s->fps = fps; - } + //TODO: Threshold of ¿1fps? in order to update fps parameter. Now a higher fps is fixed to 30fps... + //if (fps > s->fps + 1 || fps < s->fps - 1) { + // debug_msg( + // "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); + // s->frame->fps = fps; + // s->fps = fps; + // } } s->frames++; s->grab = false; @@ -387,7 +386,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { (s->required_connections) * sizeof(struct rtp *)); s->participants = pdb_init(); - s->rx_data = malloc(sizeof(struct recieved_data)); + s->rx_data = malloc(sizeof(struct std_frame_received)); s->new_frame = false; s->in_codec = malloc(sizeof(uint32_t *) * 10); @@ -523,12 +522,15 @@ vidcap_rtsp_init(const struct vidcap_params *params) { s->data = malloc(4 * s->width * s->height + s->nals_size); s->frame = vf_alloc(1); + s->frame->isStd = TRUE; + s->frame->h264_bframe = FALSE; + s->frame->h264_iframe = FALSE; s->tile = vf_get_tile(s->frame, 0); vf_get_tile(s->frame, 0)->width = s->width; vf_get_tile(s->frame, 0)->height = s->height; //TODO fps should be autodetected, now reset and controlled at vidcap_grab function - s->frame->fps = 60; - s->fps = 60; + s->frame->fps = 30; + s->fps = 30; s->frame->interlacing = PROGRESSIVE; s->frame->tiles[0].data = calloc(1, s->width * s->height); diff --git a/src/video_capture/rtsp.h b/src/video_capture/rtsp.h index 7fde29818..0cf3e5fe9 100644 --- a/src/video_capture/rtsp.h +++ b/src/video_capture/rtsp.h @@ -42,14 +42,16 @@ extern "C" { struct audio_frame; #define VIDCAP_RTSP_ID 0x45b3d828 //md5 hash of VIDCAP_RTSP_ID string == a208d26f519a2664a48781c845b3d828 - struct vidcap_type * - vidcap_rtsp_probe(void); - void * - vidcap_rtsp_init(const struct vidcap_params *params); - void - vidcap_rtsp_done(void *state); - struct video_frame * - vidcap_rtsp_grab(void *state, struct audio_frame **audio); + +struct vidcap_type * +vidcap_rtsp_probe(void); +void * +vidcap_rtsp_init(const struct vidcap_params *params); +void +vidcap_rtsp_done(void *state); +struct video_frame * +vidcap_rtsp_grab(void *state, struct audio_frame **audio); + #endif #ifdef __cplusplus From 0a054740e78e19debaa87e1654ba297da3af0916 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Tue, 15 Oct 2013 13:11:33 +0200 Subject: [PATCH 08/57] module MODULE_CLASS_MUXER created and first implementation into muxer DONE --- src/module.c | 1 + src/module.h | 1 + src/video_capture/muxer.c | 80 ++++++++++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/module.c b/src/module.c index df102e01d..d0e4f0251 100644 --- a/src/module.c +++ b/src/module.c @@ -132,6 +132,7 @@ const char *module_class_name_pairs[] = { [MODULE_CLASS_CONTROL] = "control", [MODULE_CLASS_CAPTURE] = "capture", [MODULE_CLASS_FILTER] = "filter", + [MODULE_CLASS_MUXER] = "muxer", }; const char *module_class_name(enum module_class cls) diff --git a/src/module.h b/src/module.h index 078b3f313..7ce89f646 100644 --- a/src/module.h +++ b/src/module.h @@ -74,6 +74,7 @@ enum module_class { MODULE_CLASS_CONTROL, MODULE_CLASS_CAPTURE, MODULE_CLASS_FILTER, + MODULE_CLASS_MUXER, }; struct module; diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index aa37bf575..7e6b537b1 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -46,6 +46,9 @@ #include "video.h" #include "video_capture.h" +#include "messaging.h" +#include "module.h" + #include "tv.h" #include "video_capture/muxer.h" @@ -58,6 +61,53 @@ #include #include +struct vidcap_muxer_state { + struct module mod; + + struct vidcap **devices; + int devices_cnt; + + struct video_frame *frame; + struct video_frame *prev_frame; + int frames; + struct timeval t, t0; + + int dev_index_curr; + int dev_index_next; + + int audio_source_index; +}; + +/** + * MUXER REMOTE CONTROL + */ +static int init(struct module *parent,void *state); +static void done(void *state); +static bool parse(struct vidcap_muxer_state *s, char *cfg) +{ + char *item, *save_ptr; + while ((item = strtok_r(cfg, ":", &save_ptr))) + s->dev_index_next = atoi(item); + + return true; +} + +static int init(struct module *parent, void *state) +{ + struct vidcap_muxer_state *s = calloc(1, sizeof(struct vidcap_muxer_state)); + assert(s); + + module_init_default(&s->mod); + s->mod.cls = MODULE_CLASS_MUXER; + module_register(&s->mod, parent); + + return 0; +} + +static void process_message(struct vidcap_muxer_state *s, struct msg_universal *msg) +{ + parse(s, msg->text); +} /** * MUXER CAPTURE @@ -74,21 +124,6 @@ static void show_help() } -struct vidcap_muxer_state { - struct vidcap **devices; - int devices_cnt; - - struct video_frame *frame; - struct video_frame *prev_frame; - int frames; - struct timeval t, t0; - - int dev_index_curr; - int dev_index_next; - - int audio_source_index; -}; - struct vidcap_type * vidcap_muxer_probe(void) @@ -185,8 +220,10 @@ vidcap_muxer_done(void *state) vidcap_done(s->devices[i]); } } - - vf_free(s->frame); + + module_done(&s->mod); + + vf_free(s->frame); } struct video_frame * @@ -214,6 +251,15 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) } reset_terminal_mode(); + /** + * REMOTE CONTROL + */ + struct message *msg; + while ((msg = check_message(&s->mod))) { + process_message(s,((struct msg_universal *) msg)->text); + free_message(msg); + } + /** * vidcap_grap */ From 50fd99db03ddd3c3917c0350a25edc6780f569c3 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Wed, 16 Oct 2013 12:14:04 +0200 Subject: [PATCH 09/57] remote control as muxer filter, class muxer removed --- src/capture_filter.c | 3 +++ src/module.c | 1 - src/module.h | 1 - src/video_capture/muxer.c | 46 +++++++++++++++++++++++++++++---------- src/video_capture/muxer.h | 4 ++++ 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/capture_filter.c b/src/capture_filter.c index 7cc3e9716..33d8b4811 100644 --- a/src/capture_filter.c +++ b/src/capture_filter.c @@ -61,12 +61,15 @@ #include "capture_filter/every.h" #include "capture_filter/logo.h" #include "capture_filter/none.h" +#include "video_capture/muxer.h" + static struct capture_filter_info *capture_filters[] = { &capture_filter_blank, &capture_filter_every, &capture_filter_logo, &capture_filter_none, + &capture_filter_muxer, }; struct capture_filter { diff --git a/src/module.c b/src/module.c index d0e4f0251..df102e01d 100644 --- a/src/module.c +++ b/src/module.c @@ -132,7 +132,6 @@ const char *module_class_name_pairs[] = { [MODULE_CLASS_CONTROL] = "control", [MODULE_CLASS_CAPTURE] = "capture", [MODULE_CLASS_FILTER] = "filter", - [MODULE_CLASS_MUXER] = "muxer", }; const char *module_class_name(enum module_class cls) diff --git a/src/module.h b/src/module.h index 7ce89f646..078b3f313 100644 --- a/src/module.h +++ b/src/module.h @@ -74,7 +74,6 @@ enum module_class { MODULE_CLASS_CONTROL, MODULE_CLASS_CAPTURE, MODULE_CLASS_FILTER, - MODULE_CLASS_MUXER, }; struct module; diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index 7e6b537b1..72c882f91 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -46,6 +46,7 @@ #include "video.h" #include "video_capture.h" +#include "capture_filter.h" #include "messaging.h" #include "module.h" @@ -98,17 +99,40 @@ static int init(struct module *parent, void *state) assert(s); module_init_default(&s->mod); - s->mod.cls = MODULE_CLASS_MUXER; + s->mod.cls = MODULE_CLASS_DATA; module_register(&s->mod, parent); return 0; } - +static void done(void *state) +{ + struct vidcap_muxer_state *s = state; + module_done(&s->mod); + if(state!=NULL)free(state); +} static void process_message(struct vidcap_muxer_state *s, struct msg_universal *msg) { parse(s, msg->text); } +static struct video_frame *filter(void *state, struct video_frame *in) +{ + struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; + struct message *msg; + while ((msg = check_message(&s->mod))) { + process_message(s, (struct msg_universal *) msg); + free_message(msg); + } + return in; +} + + +struct capture_filter_info capture_filter_muxer = { + .name = "muxer", + .init = init, + .done = done, + .filter = filter, +}; /** * MUXER CAPTURE */ @@ -221,8 +245,6 @@ vidcap_muxer_done(void *state) } } - module_done(&s->mod); - vf_free(s->frame); } @@ -251,14 +273,14 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) } reset_terminal_mode(); - /** - * REMOTE CONTROL - */ - struct message *msg; - while ((msg = check_message(&s->mod))) { - process_message(s,((struct msg_universal *) msg)->text); - free_message(msg); - } +// /** +// * REMOTE CONTROL +// */ +// struct message *msg; +// while ((msg = check_message(&s->mod))) { +// process_message(s,((struct msg_universal *) msg)->text); +// free_message(msg); +// } /** * vidcap_grap diff --git a/src/video_capture/muxer.h b/src/video_capture/muxer.h index 0a743b971..550d3b523 100644 --- a/src/video_capture/muxer.h +++ b/src/video_capture/muxer.h @@ -57,6 +57,10 @@ vidcap_muxer_done(void *state); struct video_frame * vidcap_muxer_grab(void *state, struct audio_frame **audio); + +struct capture_filter_info; +extern struct capture_filter_info capture_filter_muxer; + #endif #ifdef __cplusplus From f06061c458bfac11828bec8aa5c6a0e07dfb31f1 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 18 Oct 2013 11:48:21 +0200 Subject: [PATCH 10/57] muxer remote control implemented as a capture.filter muxer:#dev --- src/video_capture/muxer.c | 113 ++++++++++++++------------------------ 1 file changed, 41 insertions(+), 72 deletions(-) diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c index 72c882f91..235b1572b 100644 --- a/src/video_capture/muxer.c +++ b/src/video_capture/muxer.c @@ -77,31 +77,24 @@ struct vidcap_muxer_state { int dev_index_next; int audio_source_index; + int change; }; +static struct vidcap_muxer_state *muxer_state; /** * MUXER REMOTE CONTROL */ -static int init(struct module *parent,void *state); +static int init(struct module *parent, const char *cfg, void **state); static void done(void *state); -static bool parse(struct vidcap_muxer_state *s, char *cfg) +static struct video_frame *filter(void *state, struct video_frame *in); + +static int init(struct module *parent, const char *cfg, void **state) { - char *item, *save_ptr; - while ((item = strtok_r(cfg, ":", &save_ptr))) - s->dev_index_next = atoi(item); - - return true; -} - -static int init(struct module *parent, void *state) -{ - struct vidcap_muxer_state *s = calloc(1, sizeof(struct vidcap_muxer_state)); - assert(s); - - module_init_default(&s->mod); - s->mod.cls = MODULE_CLASS_DATA; - module_register(&s->mod, parent); + int ch = atoi(cfg); + if(ch > 0 && ch < muxer_state->devices_cnt) muxer_state->change = atoi(cfg); + //else printf("\n[MUXER REMOTE CONTROL] ERROR: devices available from 1 to %d\n",muxer_state->devices_cnt-1); + *state = muxer_state; return 0; } static void done(void *state) @@ -110,23 +103,10 @@ static void done(void *state) module_done(&s->mod); if(state!=NULL)free(state); } -static void process_message(struct vidcap_muxer_state *s, struct msg_universal *msg) -{ - parse(s, msg->text); -} - static struct video_frame *filter(void *state, struct video_frame *in) { - struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; - struct message *msg; - while ((msg = check_message(&s->mod))) { - process_message(s, (struct msg_universal *) msg); - free_message(msg); - } return in; } - - struct capture_filter_info capture_filter_muxer = { .name = "muxer", .init = init, @@ -145,7 +125,6 @@ static void show_help() printf("Usage\n"); printf("\t-t muxer -t -t ....]\n"); printf("\t\twhere devn_config is a complete configuration string of device involved in the muxer device\n"); - } @@ -166,24 +145,25 @@ vidcap_muxer_probe(void) void * vidcap_muxer_init(const struct vidcap_params *params) { - struct vidcap_muxer_state *s; + //struct vidcap_muxer_state *s; int i; printf("vidcap_muxer_init\n"); - s = (struct vidcap_muxer_state *) calloc(1, + muxer_state = (struct vidcap_muxer_state *) calloc(1, sizeof(struct vidcap_muxer_state)); - if (s == NULL) { + if (muxer_state == NULL) { printf("Unable to allocate muxer capture state\n"); return NULL; } - s->audio_source_index = -1; - s->frames = 0; - s->dev_index_curr = 0; - s->dev_index_next = 0; + muxer_state->audio_source_index = -1; + muxer_state->frames = 0; + muxer_state->dev_index_curr = 1; + muxer_state->dev_index_next = 1; + muxer_state->change = 0; - gettimeofday(&s->t0, NULL); + gettimeofday(&muxer_state->t0, NULL); if (vidcap_params_get_fmt(params) && strcmp(vidcap_params_get_fmt(params), "") != 0) @@ -192,22 +172,22 @@ vidcap_muxer_init(const struct vidcap_params *params) return &vidcap_init_noerr; } - s->devices_cnt = 0; + muxer_state->devices_cnt = 1; const struct vidcap_params *tmp = params; while ((tmp = vidcap_params_get_next(tmp))) { if (vidcap_params_get_driver(tmp) != NULL) - s->devices_cnt++; + muxer_state->devices_cnt++; else break; } - s->devices = calloc(s->devices_cnt, sizeof(struct vidcap *)); + muxer_state->devices = calloc(muxer_state->devices_cnt, sizeof(struct vidcap *)); i = 0; tmp = params; - for (int i = 0; i < s->devices_cnt; ++i) { + for (int i = 1; i < muxer_state->devices_cnt; ++i) { tmp = vidcap_params_get_next(tmp); - int ret = initialize_video_capture(NULL, tmp, &s->devices[i]); + int ret = initialize_video_capture(NULL, tmp, &muxer_state->devices[i]); if (ret != 0) { fprintf(stderr, "[muxer] Unable to initialize device %d (%s:%s).\n", i, vidcap_params_get_driver(tmp), vidcap_params_get_fmt(tmp)); @@ -215,19 +195,19 @@ vidcap_muxer_init(const struct vidcap_params *params) } } - s->frame = vf_alloc(1); + muxer_state->frame = vf_alloc(1); - return s; + return muxer_state; - error: if (s->devices) { + error: if (muxer_state->devices) { int i; - for (i = 0u; i < s->devices_cnt; ++i) { - if (s->devices[i]) { - vidcap_done(s->devices[i]); + for (i = 1u; i < muxer_state->devices_cnt; ++i) { + if (muxer_state->devices[i]) { + vidcap_done(muxer_state->devices[i]); } } } - free(s); + free(muxer_state); return NULL; } @@ -240,7 +220,7 @@ vidcap_muxer_done(void *state) if (s != NULL) { int i; - for (i = 0; i < s->devices_cnt; ++i) { + for (i = 1; i < s->devices_cnt; ++i) { vidcap_done(s->devices[i]); } } @@ -269,7 +249,7 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) if(c >= 48 && c < 48+s->devices_cnt){ // s->dev_index_curr = s->dev_index_next; s->dev_index_next = c - 48; - printf("\n[MUXER] device %d (previous was: %d) selected of %d devices...\r\n",s->dev_index_next,s->dev_index_curr,s->devices_cnt); + //printf("\n[MUXER] device %d (previous was: %d) selected of %d devices...\r\n",s->dev_index_next,s->dev_index_curr,s->devices_cnt-1); } reset_terminal_mode(); @@ -281,7 +261,10 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) // process_message(s,((struct msg_universal *) msg)->text); // free_message(msg); // } - + if(s->change != 0){ + s->dev_index_next = s->change; + s->change = 0; + } /** * vidcap_grap */ @@ -293,15 +276,15 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) frame_next = vidcap_grab(s->devices[s->dev_index_next], &audio_frame); } - printf("\n\n[MUXER] frameNext is std = %d...\n\n",frame_next->isStd); + //printf("\n\n[MUXER] frameNext is std = %d...\n\n",frame_next->isStd); if(frame_next->isStd == TRUE){ - printf("\n\n[MUXER] RTSP INCOMING FRAME...\n"); + //printf("\n\n[MUXER] RTSP INCOMING FRAME...\n"); if(frame_next->h264_iframe == TRUE){ s->dev_index_curr = s->dev_index_next; frame_curr = frame_next; - printf("[MUXER] GOT INTRA FRAME! SWITCHING...\n\n"); - }else printf("[MUXER] NO INTRA FRAME YET...\n"); + //printf("[MUXER] GOT INTRA FRAME! SWITCHING...\n\n"); + }//else printf("[MUXER] NO INTRA FRAME YET...\n"); }else{ frame_curr = frame_next; s->dev_index_curr = s->dev_index_next; @@ -322,20 +305,6 @@ vidcap_muxer_grab(void *state, struct audio_frame **audio) if (s->audio_source_index == s->dev_index_curr) { *audio = audio_frame; } -// if (frame->color_spec != s->frame->color_spec || -// frame->fps != s->frame->fps || -// frame->interlacing != s->frame->interlacing) { -// fprintf(stderr, "[muxer] Different format detected: "); -// if(frame->color_spec != s->frame->color_spec) -// fprintf(stderr, "codec"); -// if(frame->interlacing != s->frame->interlacing) -// fprintf(stderr, "interlacing"); -// if(frame->fps != s->frame->fps) -// fprintf(stderr, "FPS (%.2f and %.2f)", frame->fps, s->frame->fps); -// fprintf(stderr, "\n"); -// -// //return NULL; -// } if (frame != NULL) { vf_get_tile(s->frame, 0)->width = vf_get_tile(frame, 0)->width; vf_get_tile(s->frame, 0)->height = vf_get_tile(frame, 0)->height; From 75e2daa102ddb2be12a360e8db0c512cf9fcfc39 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 16 Jan 2014 14:39:26 +0100 Subject: [PATCH 11/57] parsing sdp for rtsp control tracks and its codecs --- src/audio/audio.c | 48 ++- src/rtp/audio_decoders.c | 104 ++++++ src/rtp/audio_decoders.h | 1 + src/video_capture/rtsp.c | 745 +++++++++++++++++++++++++-------------- 4 files changed, 638 insertions(+), 260 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index 1855a57d9..38244e5c9 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -553,10 +553,56 @@ static void *audio_receiver_thread(void *arg) } pdb_iter_done(&it); }else if(s->receiver == NET_STANDARD){ - //TODO receive mulaw standard RTP (decode frame mulaw callback) + //TODO now expecting to receive mulaw standard RTP (decode frame mulaw callback) , next steps, to be dynamic... + gettimeofday(&curr_time, NULL); + ts = tv_diff(curr_time, s->start_time) * 90000; + rtp_update(s->audio_network_device, curr_time); + rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time); + timeout.tv_sec = 0; + timeout.tv_usec = 999999 / 59.94; /* audio goes almost always at the same rate + as video frames */ + rtp_recv_r(s->audio_network_device, &timeout, ts); + pdb_iter_t it; + cp = pdb_iter_init(s->audio_participants, &it); + while (cp != NULL) { + if (audio_pbuf_decode(cp->playout_buffer, curr_time, decode_audio_frame_mulaw, &pbuf_data)) { + bool failed = false; + if(s->echo_state) { +#ifdef HAVE_SPEEX +echo_play(s->echo_state, &pbuf_data.buffer); +#endif + } + struct audio_desc curr_desc; + curr_desc = audio_desc_from_audio_frame(&pbuf_data.buffer); + if(!audio_desc_eq(device_desc, curr_desc)) { + if(audio_reconfigure(s, curr_desc.bps * 8, + curr_desc.ch_count, + curr_desc.sample_rate) != TRUE) { + fprintf(stderr, "Audio reconfiguration failed!"); + failed = true; + } + else { + fprintf(stderr, "Audio reconfiguration succeeded."); + device_desc = curr_desc; + rtp_flush_recv_buf(s->audio_network_device); + } + fprintf(stderr, " (%d channels, %d bps, %d Hz)\n", + curr_desc.ch_count, + curr_desc.bps, curr_desc.sample_rate); + + } + + if(!failed) + audio_playback_put_frame(s->audio_playback_device, &pbuf_data.buffer); + } + + pbuf_remove(cp->playout_buffer, curr_time); + cp = pdb_iter_next(&it); + } + pdb_iter_done(&it); }else { /* NET_JACK */ #ifdef HAVE_JACK_TRANS jack_receive(s->jack_connection, &pbuf_data); diff --git a/src/rtp/audio_decoders.c b/src/rtp/audio_decoders.c index cab74effa..695f261e3 100644 --- a/src/rtp/audio_decoders.c +++ b/src/rtp/audio_decoders.c @@ -564,4 +564,108 @@ cleanup: return ret; } +/* + * Second version that uses external audio configuration, + * now it uses a struct state_audio_decoder instead an audio_frame2. + * It does multi-channel handling. + */ +int decode_audio_frame_mulaw(struct coded_data *cdata, void *data) +{ + struct pbuf_audio_data *s = (struct pbuf_audio_data *) data; + struct state_audio_decoder *audio = s->decoder; + + //struct state_audio_decoder *audio = (struct state_audio_decoder *)data; + + if(!cdata) return false; + + // Reconfiguration. + if (audio->received_frame->bps != audio->saved_desc.bps || + audio->received_frame->sample_rate != audio->saved_desc.sample_rate || + audio->received_frame->ch_count != audio->saved_desc.ch_count || + audio->received_frame->codec != audio->saved_desc.codec) + { + audio_frame2_allocate(audio->received_frame, audio->saved_desc.ch_count, audio->saved_desc.sample_rate * audio->saved_desc.bps); + audio->received_frame->bps = audio->saved_desc.bps; + audio->received_frame->sample_rate = audio->saved_desc.sample_rate; + audio->received_frame->ch_count = audio->saved_desc.ch_count; + audio->received_frame->codec = audio->saved_desc.codec; + } + + // Initial setup + for (int ch = 0 ; ch < audio->received_frame->ch_count ; ch ++) { + audio->received_frame->data_len[ch] = 0; + } + + // Check-if-there-is-only-one-channel optimization. + if (audio->received_frame->ch_count == 1) { + char *to = audio->received_frame->data[0]; + + while (cdata != NULL) { + // Get the data to copy into the received_frame. + char *from = cdata->data->data; + + // See if the data fits. + if (cdata->data->data_len <= (int)(audio->received_frame->max_size - audio->received_frame->data_len[0])) { + // Copy the data + memcpy(to, from, cdata->data->data_len); + // Update the pointer and the counter. + to += cdata->data->data_len; + audio->received_frame->data_len[0] += cdata->data->data_len; + } else { + // Filled it out, exit now. + return true; + } + + cdata = cdata->nxt; + } + } else { // Multi-channel case. + + /* + * Unoptimized version of the multi-channel handling. + * TODO: Optimize it! It's a matrix transpose. + * Take a look at http://stackoverflow.com/questions/1777901/array-interleaving-problem + */ + + char *to; + int bytes_copied = 0; + + while (cdata != NULL) { + // Check that the amount of data on cdata->data->data is congruent with 0 modulus audio->received_frame->ch_count. + if (cdata->data->data_len % audio->received_frame->ch_count != 0) { + // printf something? + return false; + } + + // If there is space on the current audio_frame2 buffer. + if ((cdata->data->data_len / audio->received_frame->ch_count) <= (int)(audio->received_frame->max_size - bytes_copied)) { + char *from = cdata->data->data; + + // For each group of samples. + for (int g = 0 ; g < (cdata->data->data_len / audio->received_frame->ch_count) ; g++) { + // Iterate throught each channel. + for (int ch = 0 ; ch < audio->received_frame->ch_count ; ch ++) { + // Copy the current sample from the RTP packet to the audio_frame2. + to = audio->received_frame->data[ch]; + to += bytes_copied; + + memcpy(to, from, audio->received_frame->bps); + + from += audio->received_frame->bps; + audio->received_frame->data_len[ch] += audio->received_frame->bps; + } + + bytes_copied += audio->received_frame->bps; + } + } else { + // Filled audio_frame2 out, exit now. + return true; + } + + cdata = cdata->nxt; + } + + } + + return true; +} diff --git a/src/rtp/audio_decoders.h b/src/rtp/audio_decoders.h index faa99e5b7..a1e69b431 100644 --- a/src/rtp/audio_decoders.h +++ b/src/rtp/audio_decoders.h @@ -54,6 +54,7 @@ struct coded_data; int decode_audio_frame(struct coded_data *cdata, void *data); +int decode_audio_frame_mulaw(struct coded_data *cdata, void *data); void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const char *encryption); void audio_decoder_destroy(void *state); diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 7543d4668..67496d8b9 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -81,17 +81,17 @@ /* error handling macros */ #define my_curl_easy_setopt(A, B, C) \ if ((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK){ \ -fprintf(stderr, "[rtsp error] curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ -printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ -exit(0); \ -} + fprintf(stderr, "[rtsp error] curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ + printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ + exit(0); \ + } #define my_curl_easy_perform(A) \ if ((res = curl_easy_perform((A))) != CURLE_OK){ \ -fprintf(stderr, "[rtsp error] curl_easy_perform(%s) failed: %d\n", #A, res); \ -printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ -exit(0); \ -} + fprintf(stderr, "[rtsp error] curl_easy_perform(%s) failed: %d\n", #A, res); \ + printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ + exit(0); \ + } /* send RTSP GET_PARAMETERS request */ static void @@ -126,7 +126,7 @@ static void get_media_control_attribute(const char *sdp_filename, char *control); /* scan sdp file for incoming codec */ -static int +static char * set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state); static int @@ -151,17 +151,18 @@ FILE *F_video_rtsp = NULL; /** * @struct rtsp_state */ -struct rtsp_state { +struct video_rtsp_state { char *nals; int nals_size; char *data; //nals + data uint32_t *in_codec; + char *codec; + struct timeval t0, t; int frames; struct video_frame *frame; struct tile *tile; - struct audio_frame audio; int width; int height; @@ -170,12 +171,19 @@ struct rtsp_state { bool decompress; bool grab; + struct state_decompress *sd; + struct video_desc des; + char * out_frame; + + int port; + float fps; + char *control; + struct rtp *device; struct pdb *participants; struct pdb_e *cp; double rtcp_bw; int ttl; - char *addr; char *mcast_if; struct timeval curr_time; struct timeval timeout; @@ -184,28 +192,59 @@ struct rtsp_state { int required_connections; uint32_t timestamp; - int play_audio_frame; - - struct timeval last_audio_time; - unsigned int grab_audio:1; - - pthread_t rtsp_thread_id; //the worker_id + pthread_t vrtsp_thread_id; //the worker_id pthread_mutex_t lock; pthread_cond_t worker_cv; volatile bool worker_waiting; pthread_cond_t boss_cv; volatile bool boss_waiting; +}; - volatile bool should_exit; +struct audio_rtsp_state { + struct audio_frame audio; + int play_audio_frame; - struct state_decompress *sd; - struct video_desc des; - char * out_frame; + char *codec; + + struct timeval last_audio_time; + unsigned int grab_audio:1; - CURL *curl; - char *uri; int port; float fps; + + char *control; + + struct rtp *device; + struct pdb *participants; + struct pdb_e *cp; + double rtcp_bw; + int ttl; + char *mcast_if; + struct timeval curr_time; + struct timeval timeout; + struct timeval prev_time; + struct timeval start_time; + int required_connections; + uint32_t timestamp; + + pthread_t artsp_thread_id; //the worker_id + pthread_mutex_t lock; + pthread_cond_t worker_cv; + volatile bool worker_waiting; + pthread_cond_t boss_cv; + volatile bool boss_waiting; +}; + +struct rtsp_state { + CURL *curl; + char *uri; + uint avType; + char *addr; + char *sdp; + + volatile bool should_exit; + struct audio_rtsp_state *artsp_state; + struct video_rtsp_state *vrtsp_state; }; static void @@ -226,9 +265,9 @@ rtsp_keepalive(void *state) { s = (struct rtsp_state *) state; struct timeval now; gettimeofday(&now, NULL); - if (tv_diff(now, s->prev_time) >= 20) { + if (tv_diff(now, s->vrtsp_state->prev_time) >= 20) { rtsp_get_parameters(s->curl, s->uri); - gettimeofday(&s->prev_time, NULL); + gettimeofday(&s->vrtsp_state->prev_time, NULL); } } @@ -237,54 +276,54 @@ vidcap_rtsp_thread(void *arg) { struct rtsp_state *s; s = (struct rtsp_state *) arg; - gettimeofday(&s->start_time, NULL); - gettimeofday(&s->prev_time, NULL); + gettimeofday(&s->vrtsp_state->start_time, NULL); + gettimeofday(&s->vrtsp_state->prev_time, NULL); while (!s->should_exit) { - gettimeofday(&s->curr_time, NULL); - s->timestamp = tv_diff(s->curr_time, s->start_time) * 90000; - - rtsp_keepalive(s); - - rtp_update(s->device, s->curr_time); - //TODO no need of rtcp communication between ug and rtsp server? - //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); - - s->timeout.tv_sec = 0; - s->timeout.tv_usec = 10000; - - if (!rtp_recv_r(s->device, &s->timeout, s->timestamp)) { - pdb_iter_t it; - s->cp = pdb_iter_init(s->participants, &it); - - while (s->cp != NULL) { - if (pthread_mutex_trylock(&s->lock) == 0) { - { - if(s->grab){ - - while (s->new_frame && !s->should_exit) { - s->worker_waiting = true; - pthread_cond_wait(&s->worker_cv, &s->lock); - s->worker_waiting = false; - } - - if (pbuf_decode(s->cp->playout_buffer, s->curr_time, - decode_frame_h264, s->rx_data)) - { - s->new_frame = true; - } - if (s->boss_waiting) - pthread_cond_signal(&s->boss_cv); - } - } - pthread_mutex_unlock(&s->lock); - } - pbuf_remove(s->cp->playout_buffer, s->curr_time); - s->cp = pdb_iter_next(&it); - } - - pdb_iter_done(&it); - } +// gettimeofday(&s->curr_time, NULL); +// s->timestamp = tv_diff(s->curr_time, s->start_time) * 90000; +// +// rtsp_keepalive(s); +// +// rtp_update(s->device, s->curr_time); +// //TODO no need of rtcp communication between ug and rtsp server? +// //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); +// +// s->timeout.tv_sec = 0; +// s->timeout.tv_usec = 10000; +// +// if (!rtp_recv_r(s->device, &s->timeout, s->timestamp)) { +// pdb_iter_t it; +// s->cp = pdb_iter_init(s->participants, &it); +// +// while (s->cp != NULL) { +// if (pthread_mutex_trylock(&s->lock) == 0) { +// { +// if(s->grab){ +// +// while (s->new_frame && !s->should_exit) { +// s->worker_waiting = true; +// pthread_cond_wait(&s->worker_cv, &s->lock); +// s->worker_waiting = false; +// } +// +// if (pbuf_decode(s->cp->playout_buffer, s->curr_time, +// decode_frame_h264, s->rx_data)) +// { +// s->new_frame = true; +// } +// if (s->boss_waiting) +// pthread_cond_signal(&s->boss_cv); +// } +// } +// pthread_mutex_unlock(&s->lock); +// } +// pbuf_remove(s->cp->playout_buffer, s->curr_time); +// s->cp = pdb_iter_next(&it); +// } +// +// pdb_iter_done(&it); +// } } return NULL; } @@ -296,63 +335,63 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { *audio = NULL; - if(pthread_mutex_trylock(&s->lock)==0){ - { - s->grab = true; +// if(pthread_mutex_trylock(&s->lock)==0){ +// { +// s->grab = true; +// +// while (!s->new_frame) { +// s->boss_waiting = true; +// pthread_cond_wait(&s->boss_cv, &s->lock); +// s->boss_waiting = false; +// } +// +// gettimeofday(&s->curr_time, NULL); +// s->frame->h264_iframe = s->rx_data->iframe; +// s->frame->h264_iframe = s->rx_data->iframe; +// s->frame->tiles[0].data_len = s->rx_data->buffer_len; +// memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, +// s->rx_data->buffer_len); +// memcpy(s->frame->tiles[0].data, s->data, +// s->rx_data->buffer_len + s->nals_size); +// s->frame->tiles[0].data_len += s->nals_size; +// +// if (s->decompress) { +// decompress_frame(s->sd, (unsigned char *) s->out_frame, +// (unsigned char *) s->frame->tiles[0].data, +// s->rx_data->buffer_len + s->nals_size, 0); +// s->frame->tiles[0].data = s->out_frame; //TODO memcpy? +// s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) +// * s->des.height; //TODO reconfigurable? +// } +// s->new_frame = false; +// +// if (s->worker_waiting) { +// pthread_cond_signal(&s->worker_cv); +// } +// } +// pthread_mutex_unlock(&s->lock); +// +// gettimeofday(&s->t, NULL); +// double seconds = tv_diff(s->t, s->t0); +// if (seconds >= 5) { +// float fps = s->frames / seconds; +// fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", +// s->frames, seconds, fps); +// s->t0 = s->t; +// s->frames = 0; +// //TODO: Threshold of ¿1fps? in order to update fps parameter. Now a higher fps is fixed to 30fps... +// //if (fps > s->fps + 1 || fps < s->fps - 1) { +// // debug_msg( +// // "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); +// // s->frame->fps = fps; +// // s->fps = fps; +// // } +// } +// s->frames++; +// s->grab = false; +// } - while (!s->new_frame) { - s->boss_waiting = true; - pthread_cond_wait(&s->boss_cv, &s->lock); - s->boss_waiting = false; - } - - gettimeofday(&s->curr_time, NULL); - s->frame->h264_iframe = s->rx_data->iframe; - s->frame->h264_iframe = s->rx_data->iframe; - s->frame->tiles[0].data_len = s->rx_data->buffer_len; - memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, - s->rx_data->buffer_len); - memcpy(s->frame->tiles[0].data, s->data, - s->rx_data->buffer_len + s->nals_size); - s->frame->tiles[0].data_len += s->nals_size; - - if (s->decompress) { - decompress_frame(s->sd, (unsigned char *) s->out_frame, - (unsigned char *) s->frame->tiles[0].data, - s->rx_data->buffer_len + s->nals_size, 0); - s->frame->tiles[0].data = s->out_frame; //TODO memcpy? - s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) - * s->des.height; //TODO reconfigurable? - } - s->new_frame = false; - - if (s->worker_waiting) { - pthread_cond_signal(&s->worker_cv); - } - } - pthread_mutex_unlock(&s->lock); - - gettimeofday(&s->t, NULL); - double seconds = tv_diff(s->t, s->t0); - if (seconds >= 5) { - float fps = s->frames / seconds; - fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", - s->frames, seconds, fps); - s->t0 = s->t; - s->frames = 0; - //TODO: Threshold of ¿1fps? in order to update fps parameter. Now a higher fps is fixed to 30fps... - //if (fps > s->fps + 1 || fps < s->fps - 1) { - // debug_msg( - // "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); - // s->frame->fps = fps; - // s->fps = fps; - // } - } - s->frames++; - s->grab = false; - } - - return s->frame; + return s->vrtsp_state->frame; } void * @@ -364,32 +403,42 @@ vidcap_rtsp_init(const struct vidcap_params *params) { if (!s) return NULL; - char *save_ptr = NULL; + s->artsp_state = calloc(1,sizeof(struct audio_rtsp_state)); + s->vrtsp_state = calloc(1,sizeof(struct video_rtsp_state)); - gettimeofday(&s->t0, NULL); - s->frames = 0; - s->nals = malloc(1024); - s->grab = false; + //TODO now static codec assignment, to be dynamic as a function of supported codecs + s->vrtsp_state->codec = ""; + s->artsp_state->codec = ""; + s->artsp_state->control = ""; + s->artsp_state->control = ""; + + char *save_ptr = NULL; + s->avType = -1; //-1 none, 0 a&v, 1 v, 2 a + + gettimeofday(&s->vrtsp_state->t0, NULL); + s->vrtsp_state->frames = 0; + s->vrtsp_state->nals = malloc(1024); + s->vrtsp_state->grab = false; s->addr = "127.0.0.1"; - s->device = NULL; - s->rtcp_bw = 5 * 1024 * 1024; /* FIXME */ - s->ttl = 255; + s->vrtsp_state->device = NULL; + s->vrtsp_state->rtcp_bw = 5 * 1024 * 1024; /* FIXME */ + s->vrtsp_state->ttl = 255; - s->mcast_if = NULL; - s->required_connections = 1; + s->vrtsp_state->mcast_if = NULL; + s->vrtsp_state->required_connections = 1; - s->timeout.tv_sec = 0; - s->timeout.tv_usec = 10000; + s->vrtsp_state->timeout.tv_sec = 0; + s->vrtsp_state->timeout.tv_usec = 10000; - s->device = (struct rtp *) malloc( - (s->required_connections) * sizeof(struct rtp *)); - s->participants = pdb_init(); + s->vrtsp_state->device = (struct rtp *) malloc( + (s->vrtsp_state->required_connections) * sizeof(struct rtp *)); + s->vrtsp_state->participants = pdb_init(); - s->rx_data = malloc(sizeof(struct std_frame_received)); - s->new_frame = false; + s->vrtsp_state->rx_data = malloc(sizeof(struct std_frame_received)); + s->vrtsp_state->new_frame = false; - s->in_codec = malloc(sizeof(uint32_t *) * 10); + s->vrtsp_state->in_codec = malloc(sizeof(uint32_t *) * 10); s->uri = NULL; s->curl = NULL; @@ -427,7 +476,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { break; case 1: if (tmp) { //TODO check if it's a number - s->port = atoi(tmp); + s->vrtsp_state->port = atoi(tmp); } else { printf("\n[rtsp] Wrong format for port! \n"); show_help(); @@ -436,7 +485,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { break; case 2: if (tmp) { //TODO check if it's a number - s->width = atoi(tmp); + s->vrtsp_state->width = atoi(tmp); } else { printf("\n[rtsp] Wrong format for width! \n"); show_help(); @@ -445,20 +494,20 @@ vidcap_rtsp_init(const struct vidcap_params *params) { break; case 3: if (tmp) { //TODO check if it's a number - s->height = atoi(tmp); + s->vrtsp_state->height = atoi(tmp); //Now checking if we have user and password parameters... - if (s->height == 0) { + if (s->vrtsp_state->height == 0) { int ntmp = 0; - ntmp = s->width; - s->width = s->port; - s->height = ntmp; + ntmp = s->vrtsp_state->width; + s->vrtsp_state->width = s->vrtsp_state->port; + s->vrtsp_state->height = ntmp; sprintf(s->uri, "rtsp:%s", uri_tmp1); - s->port = atoi(uri_tmp2); + s->vrtsp_state->port = atoi(uri_tmp2); if (tmp) { if (strcmp(tmp, "true") == 0) - s->decompress = true; + s->vrtsp_state->decompress = true; else if (strcmp(tmp, "false") == 0) - s->decompress = false; + s->vrtsp_state->decompress = false; else { printf( "\n[rtsp] Wrong format for boolean decompress flag! \n"); @@ -477,9 +526,9 @@ vidcap_rtsp_init(const struct vidcap_params *params) { case 4: if (tmp) { if (strcmp(tmp, "true") == 0) - s->decompress = true; + s->vrtsp_state->decompress = true; else if (strcmp(tmp, "false") == 0) - s->decompress = false; + s->vrtsp_state->decompress = false; else { printf( "\n[rtsp] Wrong format for boolean decompress flag! \n"); @@ -497,96 +546,98 @@ vidcap_rtsp_init(const struct vidcap_params *params) { } } //re-check parameters - if (s->height == 0) { + if (s->vrtsp_state->height == 0) { int ntmp = 0; - ntmp = s->width; - s->width = (int) s->port; - s->height = (int) ntmp; + ntmp = s->vrtsp_state->width; + s->vrtsp_state->width = (int) s->vrtsp_state->port; + s->vrtsp_state->height = (int) ntmp; sprintf(s->uri, "rtsp:%s", uri_tmp1); - s->port = (int) atoi(uri_tmp2); + s->vrtsp_state->port = (int) atoi(uri_tmp2); } debug_msg("[rtsp] selected flags:\n"); debug_msg("\t uri: %s\n",s->uri); - debug_msg("\t port: %d\n", s->port); - debug_msg("\t width: %d\n",s->width); - debug_msg("\t height: %d\n",s->height); - debug_msg("\t decompress: %d\n\n",s->decompress); + debug_msg("\t port: %d\n", s->vrtsp_state->port); + debug_msg("\t width: %d\n",s->vrtsp_state->width); + debug_msg("\t height: %d\n",s->vrtsp_state->height); + debug_msg("\t decompress: %d\n\n",s->vrtsp_state->decompress); if (uri_tmp1 != NULL) free(uri_tmp1); if (uri_tmp2 != NULL) free(uri_tmp2); - s->rx_data->frame_buffer = malloc(4 * s->width * s->height); - s->data = malloc(4 * s->width * s->height + s->nals_size); + s->vrtsp_state->rx_data->frame_buffer = malloc(4 * s->vrtsp_state->width * s->vrtsp_state->height); + s->vrtsp_state->data = malloc(4 * s->vrtsp_state->width * s->vrtsp_state->height + s->vrtsp_state->nals_size); - s->frame = vf_alloc(1); - s->frame->isStd = TRUE; - s->frame->h264_bframe = FALSE; - s->frame->h264_iframe = FALSE; - s->tile = vf_get_tile(s->frame, 0); - vf_get_tile(s->frame, 0)->width = s->width; - vf_get_tile(s->frame, 0)->height = s->height; + s->vrtsp_state->frame = vf_alloc(1); + s->vrtsp_state->frame->isStd = TRUE; + s->vrtsp_state->frame->h264_bframe = FALSE; + s->vrtsp_state->frame->h264_iframe = FALSE; + s->vrtsp_state->tile = vf_get_tile(s->vrtsp_state->frame, 0); + vf_get_tile(s->vrtsp_state->frame, 0)->width = s->vrtsp_state->width; + vf_get_tile(s->vrtsp_state->frame, 0)->height = s->vrtsp_state->height; //TODO fps should be autodetected, now reset and controlled at vidcap_grab function - s->frame->fps = 30; - s->fps = 30; - s->frame->interlacing = PROGRESSIVE; + s->vrtsp_state->frame->fps = 30; + s->vrtsp_state->fps = 30; + s->vrtsp_state->frame->interlacing = PROGRESSIVE; - s->frame->tiles[0].data = calloc(1, s->width * s->height); + s->vrtsp_state->frame->tiles[0].data = calloc(1, s->vrtsp_state->width * s->vrtsp_state->height); s->should_exit = false; - s->device = rtp_init_if(NULL, s->mcast_if, s->port, 0, s->ttl, s->rtcp_bw, - 0, rtp_recv_callback, (void *) s->participants, 0); + s->vrtsp_state->nals_size = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->nals); - if (s->device != NULL) { - if (!rtp_set_option(s->device, RTP_OPT_WEAK_VALIDATION, 1)) { - debug_msg("[rtsp] RTP INIT - set option\n"); - return NULL; - } - if (!rtp_set_sdes(s->device, rtp_my_ssrc(s->device), - RTCP_SDES_TOOL, PACKAGE_STRING, strlen(PACKAGE_STRING))) { - debug_msg("[rtsp] RTP INIT - set sdes\n"); - return NULL; - } - int ret = rtp_set_recv_buf(s->device, INITIAL_VIDEO_RECV_BUFFER_SIZE); - if (!ret) { - debug_msg("[rtsp] RTP INIT - set recv buf \nset command: sudo sysctl -w net.core.rmem_max=9123840\n"); - return NULL; - } - - if (!rtp_set_send_buf(s->device, 1024 * 56)) { - debug_msg("[rtsp] RTP INIT - set send buf\n"); - return NULL; - } - ret=pdb_add(s->participants, rtp_my_ssrc(s->device)); - } +// s->device = rtp_init_if(NULL, s->mcast_if, s->port, 0, s->ttl, s->rtcp_bw, +// 0, rtp_recv_callback, (void *) s->participants, 0); +// +// if (s->device != NULL) { +// if (!rtp_set_option(s->device, RTP_OPT_WEAK_VALIDATION, 1)) { +// debug_msg("[rtsp] RTP INIT - set option\n"); +// return NULL; +// } +// if (!rtp_set_sdes(s->device, rtp_my_ssrc(s->device), +// RTCP_SDES_TOOL, PACKAGE_STRING, strlen(PACKAGE_STRING))) { +// debug_msg("[rtsp] RTP INIT - set sdes\n"); +// return NULL; +// } +// +// int ret = rtp_set_recv_buf(s->device, INITIAL_VIDEO_RECV_BUFFER_SIZE); +// if (!ret) { +// debug_msg("[rtsp] RTP INIT - set recv buf \nset command: sudo sysctl -w net.core.rmem_max=9123840\n"); +// return NULL; +// } +// +// if (!rtp_set_send_buf(s->device, 1024 * 56)) { +// debug_msg("[rtsp] RTP INIT - set send buf\n"); +// return NULL; +// } +// ret=pdb_add(s->participants, rtp_my_ssrc(s->device)); +// } debug_msg("[rtsp] rtp receiver init done\n"); - pthread_mutex_init(&s->lock, NULL); - pthread_cond_init(&s->boss_cv, NULL); - pthread_cond_init(&s->worker_cv, NULL); + pthread_mutex_init(&s->vrtsp_state->lock, NULL); + pthread_cond_init(&s->vrtsp_state->boss_cv, NULL); + pthread_cond_init(&s->vrtsp_state->worker_cv, NULL); - s->boss_waiting = false; - s->worker_waiting = false; + s->vrtsp_state->boss_waiting = false; + s->vrtsp_state->worker_waiting = false; - s->nals_size = init_rtsp(s->uri, s->port, s, s->nals); - if (s->nals_size >= 0) - memcpy(s->data, s->nals, s->nals_size); + if (s->vrtsp_state->nals_size >= 0) + memcpy(s->vrtsp_state->data, s->vrtsp_state->nals, s->vrtsp_state->nals_size); else return NULL; - if (s->decompress) { - if (init_decompressor(s) == 0) + if (s->vrtsp_state->decompress) { + if (init_decompressor(s->vrtsp_state) == 0) return NULL; - s->frame->color_spec = UYVY; + s->vrtsp_state->frame->color_spec = UYVY; } - pthread_create(&s->rtsp_thread_id, NULL, vidcap_rtsp_thread, s); + pthread_create(&s->vrtsp_state->vrtsp_thread_id, NULL, vidcap_rtsp_thread, s); debug_msg("[rtsp] rtsp capture init done\n"); @@ -611,11 +662,18 @@ init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals) { char *sdp_filename = malloc(strlen(url) + 32); char *control = malloc(150 * sizeof(char *)); memset(control, 0, 150 * sizeof(char *)); - char transport[256]; - bzero(transport, 256); + char Atransport[256]; + char Vtransport[256]; + bzero(Atransport, 256); + bzero(Vtransport, 256); int port = rtsp_port; + get_sdp_filename(url, sdp_filename); - sprintf(transport, "RTP/AVP;unicast;client_port=%d-%d", port, port + 1); + + sprintf(Vtransport, "RTP/AVP;unicast;client_port=%d-%d", port, port + 1); + + //THIS AUDIO PORTS ARE AS DEFAULT UG AUDIO PORTS BUT AREN'T RELATED... + sprintf(Atransport, "RTP/AVP;unicast;client_port=%d-%d", port+2, port + 3); /* initialize curl */ res = curl_global_init(CURL_GLOBAL_ALL); @@ -645,24 +703,51 @@ init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals) { /* request server options */ rtsp_options(curl, uri); - debug_msg("sdp_file: %s\n", sdp_filename); + printf("sdp_file: %s\n", sdp_filename); /* request session description and write response to sdp file */ rtsp_describe(curl, uri, sdp_filename); - debug_msg("sdp_file!!!!: %s\n", sdp_filename); - /* get media control attribute from sdp file */ - get_media_control_attribute(sdp_filename, control); +// printf("sdp_file name: %s\n", sdp_filename); - /* set incoming media codec attribute from sdp file */ - if (set_codec_attribute_from_incoming_media(sdp_filename, s) == 0) + setup_codecs_and_controls_from_sdp(sdp_filename, s); + if (s->vrtsp_state->codec == "H264"){ + sprintf(uri, "%s/%s", url, s->vrtsp_state->control); + printf("\n V URI = %s\n",uri); + rtsp_setup(curl, uri, Vtransport); + //rtsp_play(curl, uri, range); + sprintf(uri, "%s", url); + } + if (s->artsp_state->codec == "PCMU"){ + sprintf(uri, "%s/%s", url, s->artsp_state->control); + printf("\n A URI = %s\n",uri); + rtsp_setup(curl, uri, Atransport); + //rtsp_play(curl, uri, range); + sprintf(uri, "%s", url); + } + if (s->artsp_state->codec == "" && s->vrtsp_state->codec == ""){ return -1; + }else rtsp_play(curl, uri, range); - /* setup media stream */ - sprintf(uri, "%s/%s", url, control); - rtsp_setup(curl, uri, transport); - /* start playing media stream */ - sprintf(uri, "%s", url); - rtsp_play(curl, uri, range); +// /* set incoming media codec attribute from sdp file */ +// //FIND VIDEO TRACK (NOW ONLY H264 IS ACCEPTED) +// char * codec1 = set_codec_attribute_from_incoming_media(sdp_filename, s); //AQUÍ ACTIVAR VIDEO H264 SI EXISTEIX I/O AUDIO ULAW SI EXISTEIX +// if (codec1 == NULL) +// return -1; +// else { /* get media control attribute from sdp file */ +// get_media_control_attribute(sdp_filename, control); +// printf("\nmedia control attribute: %s\n\n", control); +// /* setup media stream */ +// sprintf(uri, "%s/%s", url, control); +// printf("setup: %s\n", uri); +// rtsp_setup(curl, uri, Vtransport); +// +// // exit(0); +// /* start playing media stream */ +// sprintf(uri, "%s", url); +// +// +// } +// rtsp_play(curl, uri, range); /* get start nal size attribute from sdp file */ len_nals = get_nals(sdp_filename, nals); @@ -682,6 +767,108 @@ init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals) { return len_nals; } +void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { + struct rtsp_state *rtspState; + rtspState = (struct rtsp_state *) state; + + int n=0; + char *line = (char*) malloc(1024); + char* tmpBuff; + int countT = 0; + int countC = 0; + char* codecs[2]; + char* tracks[2]; + for(int q=0; q<2 ; q++){ + codecs[q] = (char*) malloc(10); + tracks[q] = (char*) malloc(10); + } + + FILE* fp; + + fp = fopen(sdp_filename, "r"); + if(fp == 0){ + printf("unable to open asset %s", sdp_filename); + fclose(fp); + return -1; + } + fseek(fp, 0, SEEK_END); + unsigned long fileSize = ftell(fp); + rewind(fp); + + char* buffer = (char*) malloc(fileSize+1); + unsigned long readResult = fread(buffer, sizeof(char), fileSize, fp); + + if(readResult != fileSize){ + printf("something bad happens, read result != file size"); + return -1; + } + buffer[fileSize] = '\0'; + + while (buffer[n] != '\0'){ + newLine(buffer,&n,line); + sscanf(line, " a = control: %s", tmpBuff); + tmpBuff = strstr(line, "track"); + if(tmpBuff!=NULL){ + //printf("track = %s\n",tmpBuff); + strncpy(tracks[countT],tmpBuff,strlen(tmpBuff)); + tracks[countT][strlen(tmpBuff)] = '\0'; + countT++; + } + tmpBuff='\0'; + sscanf(line, " a=rtpmap:96 %s", tmpBuff); + tmpBuff = strstr(line, "H264"); + if(tmpBuff!=NULL){ + //printf("codec = %s\n",tmpBuff); + strncpy(codecs[countC],tmpBuff,4); + codecs[countC][4] = '\0'; + countC++; + } + tmpBuff='\0'; + sscanf(line, " a=rtpmap:97 %s", tmpBuff); + tmpBuff = strstr(line, "PCMU"); + if(tmpBuff!=NULL){ + //printf("codec = %s\n",tmpBuff); + strncpy(codecs[countC],tmpBuff,4); + codecs[countC][4] = '\0'; + countC++; + } + tmpBuff='\0'; + + if(countT > 1 && countC > 1) break; + } + printf("\nTRACK = %s FOR CODEC = %s",tracks[0],codecs[0]); + printf("\nTRACK = %s FOR CODEC = %s\n",tracks[1],codecs[1]); + + for(int p=0;p<2;p++){ + if(strncmp(codecs[p],"H264",4)==0){ + rtspState->vrtsp_state->codec = "H264"; + rtspState->vrtsp_state->control = tracks[p]; + }if(strncmp(codecs[p],"PCMU",4)==0){ + rtspState->artsp_state->codec = "PCMU"; + rtspState->artsp_state->control = tracks[p]; + } + } + free(line); + free(buffer); + fclose(fp); +} + +void newLine(const char* buffer, int* i, char* line){ + int j=0; + while(buffer[*i] != '\n' && buffer[*i] != '\0'){ + j++; + (*i)++; + } + if(buffer[*i] == '\n'){ + j++; + (*i)++; + } + + if(j>0){ + memcpy(line,buffer+(*i)-j,j); + line[j] = '\0'; + } +} /** * Initializes decompressor if required by decompress flag */ @@ -690,24 +877,24 @@ init_decompressor(void *state) { struct rtsp_state *sr; sr = (struct rtsp_state *) state; - sr->sd = (struct state_decompress *) calloc(2, + sr->vrtsp_state->sd = (struct state_decompress *) calloc(2, sizeof(struct state_decompress *)); initialize_video_decompress(); if (decompress_is_available(LIBAVCODEC_MAGIC)) { - sr->sd = decompress_init(LIBAVCODEC_MAGIC); + sr->vrtsp_state->sd = decompress_init(LIBAVCODEC_MAGIC); - sr->des.width = sr->width; - sr->des.height = sr->height; - sr->des.color_spec = sr->frame->color_spec; - sr->des.tile_count = 0; - sr->des.interlacing = PROGRESSIVE; + sr->vrtsp_state->des.width = sr->vrtsp_state->width; + sr->vrtsp_state->des.height = sr->vrtsp_state->height; + sr->vrtsp_state->des.color_spec = sr->vrtsp_state->frame->color_spec; + sr->vrtsp_state->des.tile_count = 0; + sr->vrtsp_state->des.interlacing = PROGRESSIVE; - decompress_reconfigure(sr->sd, sr->des, 16, 8, 0, - vc_get_linesize(sr->des.width, UYVY), UYVY); + decompress_reconfigure(sr->vrtsp_state->sd, sr->vrtsp_state->des, 16, 8, 0, + vc_get_linesize(sr->vrtsp_state->des.width, UYVY), UYVY); } else return 0; - sr->out_frame = malloc(sr->width * sr->height * 4); + sr->vrtsp_state->out_frame = malloc(sr->vrtsp_state->width * sr->vrtsp_state->height * 4); return 1; } @@ -838,17 +1025,21 @@ get_sdp_filename(const char *url, char *sdp_filename) { * scan sdp file for media control attribute */ static void -get_media_control_attribute(const char *sdp_filename, char *control) { +check_and_set_media_control_attribute(const char *sdp_filename, void *state) { + struct rtsp_state *rtspState; + rtspState = (struct rtsp_state *) state; + int max_len = 1256; char *s = malloc(max_len); char *track = malloc(max_len); char *track_ant = malloc(max_len); - + printf("\n\n"); FILE *sdp_fp = fopen(sdp_filename, "rt"); //control[0] = '\0'; if (sdp_fp != NULL) { while (fgets(s, max_len - 2, sdp_fp) != NULL) { + printf("\nSDP: %s\n",s); sscanf(s, " a = control: %s", track_ant); if (strcmp(track_ant, "") != 0) { track = strstr(track_ant, "track"); @@ -856,7 +1047,34 @@ get_media_control_attribute(const char *sdp_filename, char *control) { break; } } + printf("\n\n"); + fclose(sdp_fp); + } + free(s); + memcpy(rtspState->vrtsp_state->control, track, strlen(track)); +} +static void +get_media_control_attribute(const char *sdp_filename, char *control) { + int max_len = 1256; + char *s = malloc(max_len); + + char *track = malloc(max_len); + char *track_ant = malloc(max_len); + printf("\n\n"); + FILE *sdp_fp = fopen(sdp_filename, "rt"); + //control[0] = '\0'; + if (sdp_fp != NULL) { + while (fgets(s, max_len - 2, sdp_fp) != NULL) { + printf("\nSDP: %s\n",s); + sscanf(s, " a = control: %s", track_ant); + if (strcmp(track_ant, "") != 0) { + track = strstr(track_ant, "track"); + if (track != NULL) + break; + } + } + printf("\n\n"); fclose(sdp_fp); } free(s); @@ -866,7 +1084,7 @@ get_media_control_attribute(const char *sdp_filename, char *control) { /** * scan sdp file for incoming codec and set it */ -static int +static char * set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state) { struct rtsp_state *sr; sr = (struct rtsp_state *) state; @@ -901,17 +1119,26 @@ set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state) { tmp = strtok_r(codec, "/", &save_ptr); if (!tmp) { fprintf(stderr, "[rtsp] no codec atribute found into sdp file...\n"); - return 0; + return NULL; } - sprintf((char *) sr->in_codec, "%s", tmp); - if (memcmp(sr->in_codec, "H264", 4) == 0) - sr->frame->color_spec = H264; - else if (memcmp(sr->in_codec, "VP8", 3) == 0) - sr->frame->color_spec = VP8; - else - sr->frame->color_spec = RGBA; - return 1; + printf("\n\nCODEC = %s\n\n",tmp); + + sprintf((char *) sr->vrtsp_state->in_codec, "%s", tmp); + + if (memcmp(sr->vrtsp_state->in_codec, "H264", 4) == 0){ + sr->vrtsp_state->frame->color_spec = H264; + return "H264"; + } + else if (memcmp(sr->vrtsp_state->in_codec, "VP8", 3) == 0){ + sr->vrtsp_state->frame->color_spec = VP8; + return "VP8"; + } + else{ + sr->vrtsp_state->frame->color_spec = RGBA; + return "RGBA"; + } + return NULL; } struct vidcap_type * @@ -932,19 +1159,19 @@ vidcap_rtsp_done(void *state) { struct rtsp_state *s = state; s->should_exit = true; - pthread_join(s->rtsp_thread_id, NULL); + pthread_join(s->vrtsp_state->vrtsp_thread_id, NULL); - free(s->rx_data->frame_buffer); - free(s->data); + free(s->vrtsp_state->rx_data->frame_buffer); + free(s->vrtsp_state->data); rtsp_teardown(s->curl, s->uri); curl_easy_cleanup(s->curl); s->curl = NULL; - if (s->decompress) - decompress_done(s->sd); - rtp_done(s->device); + if (s->vrtsp_state->decompress) + decompress_done(s->vrtsp_state->sd); + rtp_done(s->vrtsp_state->device); free(s); } From 000d0afd3c0005a68957713013166499691ee9d0 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 24 Jan 2014 18:35:12 +0100 Subject: [PATCH 12/57] new parser for supported codec and track assignment working with video, todo - audio --- src/video_capture/rtsp.c | 452 +++++++++++++-------------------------- 1 file changed, 149 insertions(+), 303 deletions(-) diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 67496d8b9..4882015e0 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -121,14 +121,6 @@ rtsp_teardown(CURL *curl, const char *uri); static void get_sdp_filename(const char *url, char *sdp_filename); -/* scan sdp file for media control attribute */ -static void -get_media_control_attribute(const char *sdp_filename, char *control); - -/* scan sdp file for incoming codec */ -static char * -set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state); - static int get_nals(const char *sdp_filename, char *nals); @@ -280,50 +272,49 @@ vidcap_rtsp_thread(void *arg) { gettimeofday(&s->vrtsp_state->prev_time, NULL); while (!s->should_exit) { -// gettimeofday(&s->curr_time, NULL); -// s->timestamp = tv_diff(s->curr_time, s->start_time) * 90000; -// -// rtsp_keepalive(s); -// -// rtp_update(s->device, s->curr_time); -// //TODO no need of rtcp communication between ug and rtsp server? -// //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); -// -// s->timeout.tv_sec = 0; -// s->timeout.tv_usec = 10000; -// -// if (!rtp_recv_r(s->device, &s->timeout, s->timestamp)) { -// pdb_iter_t it; -// s->cp = pdb_iter_init(s->participants, &it); -// -// while (s->cp != NULL) { -// if (pthread_mutex_trylock(&s->lock) == 0) { -// { -// if(s->grab){ -// -// while (s->new_frame && !s->should_exit) { -// s->worker_waiting = true; -// pthread_cond_wait(&s->worker_cv, &s->lock); -// s->worker_waiting = false; -// } -// -// if (pbuf_decode(s->cp->playout_buffer, s->curr_time, -// decode_frame_h264, s->rx_data)) -// { -// s->new_frame = true; -// } -// if (s->boss_waiting) -// pthread_cond_signal(&s->boss_cv); -// } -// } -// pthread_mutex_unlock(&s->lock); -// } -// pbuf_remove(s->cp->playout_buffer, s->curr_time); -// s->cp = pdb_iter_next(&it); -// } -// -// pdb_iter_done(&it); -// } + gettimeofday(&s->vrtsp_state->curr_time, NULL); + s->vrtsp_state->timestamp = tv_diff(s->vrtsp_state->curr_time, s->vrtsp_state->start_time) * 90000; + + rtsp_keepalive(s); + + rtp_update(s->vrtsp_state->device, s->vrtsp_state->curr_time); + //TODO no need of rtcp communication between ug and rtsp server? + //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); + + s->vrtsp_state->timeout.tv_sec = 0; + s->vrtsp_state->timeout.tv_usec = 10000; + + if (!rtp_recv_r(s->vrtsp_state->device, &s->vrtsp_state->timeout, s->vrtsp_state->timestamp)) { + pdb_iter_t it; + s->vrtsp_state->cp = pdb_iter_init(s->vrtsp_state->participants, &it); + + while (s->vrtsp_state->cp != NULL) { + if (pthread_mutex_trylock(&s->vrtsp_state->lock) == 0) { + { + if(s->vrtsp_state->grab){ + + while (s->vrtsp_state->new_frame && !s->should_exit) { + s->vrtsp_state->worker_waiting = true; + pthread_cond_wait(&s->vrtsp_state->worker_cv, &s->vrtsp_state->lock); + s->vrtsp_state->worker_waiting = false; + } + if (pbuf_decode(s->vrtsp_state->cp->playout_buffer, s->vrtsp_state->curr_time, + decode_frame_h264, s->vrtsp_state->rx_data)) + { + s->vrtsp_state->new_frame = true; + } + if (s->vrtsp_state->boss_waiting) + pthread_cond_signal(&s->vrtsp_state->boss_cv); + } + } + pthread_mutex_unlock(&s->vrtsp_state->lock); + } + pbuf_remove(s->vrtsp_state->cp->playout_buffer, s->vrtsp_state->curr_time); + s->vrtsp_state->cp = pdb_iter_next(&it); + } + + pdb_iter_done(&it); + } } return NULL; } @@ -335,61 +326,61 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { *audio = NULL; -// if(pthread_mutex_trylock(&s->lock)==0){ -// { -// s->grab = true; -// -// while (!s->new_frame) { -// s->boss_waiting = true; -// pthread_cond_wait(&s->boss_cv, &s->lock); -// s->boss_waiting = false; -// } -// -// gettimeofday(&s->curr_time, NULL); -// s->frame->h264_iframe = s->rx_data->iframe; -// s->frame->h264_iframe = s->rx_data->iframe; -// s->frame->tiles[0].data_len = s->rx_data->buffer_len; -// memcpy(s->data + s->nals_size, s->rx_data->frame_buffer, -// s->rx_data->buffer_len); -// memcpy(s->frame->tiles[0].data, s->data, -// s->rx_data->buffer_len + s->nals_size); -// s->frame->tiles[0].data_len += s->nals_size; -// -// if (s->decompress) { -// decompress_frame(s->sd, (unsigned char *) s->out_frame, -// (unsigned char *) s->frame->tiles[0].data, -// s->rx_data->buffer_len + s->nals_size, 0); -// s->frame->tiles[0].data = s->out_frame; //TODO memcpy? -// s->frame->tiles[0].data_len = vc_get_linesize(s->des.width, UYVY) -// * s->des.height; //TODO reconfigurable? -// } -// s->new_frame = false; -// -// if (s->worker_waiting) { -// pthread_cond_signal(&s->worker_cv); -// } -// } -// pthread_mutex_unlock(&s->lock); -// -// gettimeofday(&s->t, NULL); -// double seconds = tv_diff(s->t, s->t0); -// if (seconds >= 5) { -// float fps = s->frames / seconds; -// fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", -// s->frames, seconds, fps); -// s->t0 = s->t; -// s->frames = 0; -// //TODO: Threshold of ¿1fps? in order to update fps parameter. Now a higher fps is fixed to 30fps... -// //if (fps > s->fps + 1 || fps < s->fps - 1) { -// // debug_msg( -// // "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); -// // s->frame->fps = fps; -// // s->fps = fps; -// // } -// } -// s->frames++; -// s->grab = false; -// } + if(pthread_mutex_trylock(&s->vrtsp_state->lock)==0){ + { + s->vrtsp_state->grab = true; + + while (!s->vrtsp_state->new_frame) { + s->vrtsp_state->boss_waiting = true; + pthread_cond_wait(&s->vrtsp_state->boss_cv, &s->vrtsp_state->lock); + s->vrtsp_state->boss_waiting = false; + } + + gettimeofday(&s->vrtsp_state->curr_time, NULL); + s->vrtsp_state->frame->h264_iframe = s->vrtsp_state->rx_data->iframe; + s->vrtsp_state->frame->h264_iframe = s->vrtsp_state->rx_data->iframe; + s->vrtsp_state->frame->tiles[0].data_len = s->vrtsp_state->rx_data->buffer_len; + memcpy(s->vrtsp_state->data + s->vrtsp_state->nals_size, s->vrtsp_state->rx_data->frame_buffer, + s->vrtsp_state->rx_data->buffer_len); + memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->data, + s->vrtsp_state->rx_data->buffer_len + s->vrtsp_state->nals_size); + s->vrtsp_state->frame->tiles[0].data_len += s->vrtsp_state->nals_size; + + if (s->vrtsp_state->decompress) { + decompress_frame(s->vrtsp_state->sd, (unsigned char *) s->vrtsp_state->out_frame, + (unsigned char *) s->vrtsp_state->frame->tiles[0].data, + s->vrtsp_state->rx_data->buffer_len + s->vrtsp_state->nals_size, 0); + s->vrtsp_state->frame->tiles[0].data = s->vrtsp_state->out_frame; //TODO memcpy? + s->vrtsp_state->frame->tiles[0].data_len = vc_get_linesize(s->vrtsp_state->des.width, UYVY) + * s->vrtsp_state->des.height; //TODO reconfigurable? + } + s->vrtsp_state->new_frame = false; + + if (s->vrtsp_state->worker_waiting) { + pthread_cond_signal(&s->vrtsp_state->worker_cv); + } + } + pthread_mutex_unlock(&s->vrtsp_state->lock); + + gettimeofday(&s->vrtsp_state->t, NULL); + double seconds = tv_diff(s->vrtsp_state->t, s->vrtsp_state->t0); + if (seconds >= 5) { + float fps = s->vrtsp_state->frames / seconds; + fprintf(stderr, "[rtsp capture] %d frames in %g seconds = %g FPS\n", + s->vrtsp_state->frames, seconds, fps); + s->vrtsp_state->t0 = s->vrtsp_state->t; + s->vrtsp_state->frames = 0; + //TODO: Threshold of ¿1fps? in order to update fps parameter. Now a higher fps is fixed to 30fps... + //if (fps > s->fps + 1 || fps < s->fps - 1) { + // debug_msg( + // "\n[rtsp] updating fps from rtsp server stream... now = %f , before = %f\n",fps,s->fps); + // s->frame->fps = fps; + // s->fps = fps; + // } + } + s->vrtsp_state->frames++; + s->vrtsp_state->grab = false; + } return s->vrtsp_state->frame; } @@ -509,8 +500,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { else if (strcmp(tmp, "false") == 0) s->vrtsp_state->decompress = false; else { - printf( - "\n[rtsp] Wrong format for boolean decompress flag! \n"); + printf("\n[rtsp] Wrong format for boolean decompress flag! \n"); show_help(); exit(0); } @@ -586,35 +576,32 @@ vidcap_rtsp_init(const struct vidcap_params *params) { s->should_exit = false; - s->vrtsp_state->nals_size = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->nals); + s->vrtsp_state->device = rtp_init_if(NULL, s->vrtsp_state->mcast_if, s->vrtsp_state->port, 0, s->vrtsp_state->ttl, s->vrtsp_state->rtcp_bw, + 0, rtp_recv_callback, (void *) s->vrtsp_state->participants, 0); + if (s->vrtsp_state->device != NULL) { + if (!rtp_set_option(s->vrtsp_state->device, RTP_OPT_WEAK_VALIDATION, 1)) { + debug_msg("[rtsp] RTP INIT - set option\n"); + return NULL; + } + if (!rtp_set_sdes(s->vrtsp_state->device, rtp_my_ssrc(s->vrtsp_state->device), + RTCP_SDES_TOOL, PACKAGE_STRING, strlen(PACKAGE_STRING))) { + debug_msg("[rtsp] RTP INIT - set sdes\n"); + return NULL; + } -// s->device = rtp_init_if(NULL, s->mcast_if, s->port, 0, s->ttl, s->rtcp_bw, -// 0, rtp_recv_callback, (void *) s->participants, 0); -// -// if (s->device != NULL) { -// if (!rtp_set_option(s->device, RTP_OPT_WEAK_VALIDATION, 1)) { -// debug_msg("[rtsp] RTP INIT - set option\n"); -// return NULL; -// } -// if (!rtp_set_sdes(s->device, rtp_my_ssrc(s->device), -// RTCP_SDES_TOOL, PACKAGE_STRING, strlen(PACKAGE_STRING))) { -// debug_msg("[rtsp] RTP INIT - set sdes\n"); -// return NULL; -// } -// -// int ret = rtp_set_recv_buf(s->device, INITIAL_VIDEO_RECV_BUFFER_SIZE); -// if (!ret) { -// debug_msg("[rtsp] RTP INIT - set recv buf \nset command: sudo sysctl -w net.core.rmem_max=9123840\n"); -// return NULL; -// } -// -// if (!rtp_set_send_buf(s->device, 1024 * 56)) { -// debug_msg("[rtsp] RTP INIT - set send buf\n"); -// return NULL; -// } -// ret=pdb_add(s->participants, rtp_my_ssrc(s->device)); -// } + int ret = rtp_set_recv_buf(s->vrtsp_state->device, INITIAL_VIDEO_RECV_BUFFER_SIZE); + if (!ret) { + debug_msg("[rtsp] RTP INIT - set recv buf \nset command: sudo sysctl -w net.core.rmem_max=9123840\n"); + return NULL; + } + + if (!rtp_set_send_buf(s->vrtsp_state->device, 1024 * 56)) { + debug_msg("[rtsp] RTP INIT - set send buf\n"); + return NULL; + } + ret=pdb_add(s->vrtsp_state->participants, rtp_my_ssrc(s->vrtsp_state->device)); + } debug_msg("[rtsp] rtp receiver init done\n"); @@ -625,11 +612,14 @@ vidcap_rtsp_init(const struct vidcap_params *params) { s->vrtsp_state->boss_waiting = false; s->vrtsp_state->worker_waiting = false; + s->vrtsp_state->nals_size = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->nals); if (s->vrtsp_state->nals_size >= 0) memcpy(s->vrtsp_state->data, s->vrtsp_state->nals, s->vrtsp_state->nals_size); - else + else{ + printf("\n[rtsp] something went wrong with the sdp parser...\n"); return NULL; + } if (s->vrtsp_state->decompress) { if (init_decompressor(s->vrtsp_state) == 0) @@ -706,48 +696,23 @@ init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals) { printf("sdp_file: %s\n", sdp_filename); /* request session description and write response to sdp file */ rtsp_describe(curl, uri, sdp_filename); -// printf("sdp_file name: %s\n", sdp_filename); setup_codecs_and_controls_from_sdp(sdp_filename, s); if (s->vrtsp_state->codec == "H264"){ + s->vrtsp_state->frame->color_spec = H264; sprintf(uri, "%s/%s", url, s->vrtsp_state->control); - printf("\n V URI = %s\n",uri); + debug_msg("\n V URI = %s\n",uri); rtsp_setup(curl, uri, Vtransport); - //rtsp_play(curl, uri, range); sprintf(uri, "%s", url); } if (s->artsp_state->codec == "PCMU"){ sprintf(uri, "%s/%s", url, s->artsp_state->control); - printf("\n A URI = %s\n",uri); + debug_msg("\n A URI = %s\n",uri); rtsp_setup(curl, uri, Atransport); - //rtsp_play(curl, uri, range); sprintf(uri, "%s", url); } - if (s->artsp_state->codec == "" && s->vrtsp_state->codec == ""){ - return -1; - }else rtsp_play(curl, uri, range); - - -// /* set incoming media codec attribute from sdp file */ -// //FIND VIDEO TRACK (NOW ONLY H264 IS ACCEPTED) -// char * codec1 = set_codec_attribute_from_incoming_media(sdp_filename, s); //AQUÍ ACTIVAR VIDEO H264 SI EXISTEIX I/O AUDIO ULAW SI EXISTEIX -// if (codec1 == NULL) -// return -1; -// else { /* get media control attribute from sdp file */ -// get_media_control_attribute(sdp_filename, control); -// printf("\nmedia control attribute: %s\n\n", control); -// /* setup media stream */ -// sprintf(uri, "%s/%s", url, control); -// printf("setup: %s\n", uri); -// rtsp_setup(curl, uri, Vtransport); -// -// // exit(0); -// /* start playing media stream */ -// sprintf(uri, "%s", url); -// -// -// } -// rtsp_play(curl, uri, range); + if (s->artsp_state->codec == "" && s->vrtsp_state->codec == "") return -1; + else rtsp_play(curl, uri, range); /* get start nal size attribute from sdp file */ len_nals = get_nals(sdp_filename, nals); @@ -810,8 +775,8 @@ void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { tmpBuff = strstr(line, "track"); if(tmpBuff!=NULL){ //printf("track = %s\n",tmpBuff); - strncpy(tracks[countT],tmpBuff,strlen(tmpBuff)); - tracks[countT][strlen(tmpBuff)] = '\0'; + strncpy(tracks[countT],tmpBuff,strlen(tmpBuff)-2); + tracks[countT][strlen(tmpBuff)-2] = '\0'; countT++; } tmpBuff='\0'; @@ -836,13 +801,14 @@ void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { if(countT > 1 && countC > 1) break; } - printf("\nTRACK = %s FOR CODEC = %s",tracks[0],codecs[0]); - printf("\nTRACK = %s FOR CODEC = %s\n",tracks[1],codecs[1]); + debug_msg("\nTRACK = %s FOR CODEC = %s",tracks[0],codecs[0]); + debug_msg("\nTRACK = %s FOR CODEC = %s\n",tracks[1],codecs[1]); for(int p=0;p<2;p++){ if(strncmp(codecs[p],"H264",4)==0){ rtspState->vrtsp_state->codec = "H264"; rtspState->vrtsp_state->control = tracks[p]; + }if(strncmp(codecs[p],"PCMU",4)==0){ rtspState->artsp_state->codec = "PCMU"; rtspState->artsp_state->control = tracks[p]; @@ -874,27 +840,27 @@ void newLine(const char* buffer, int* i, char* line){ */ static int init_decompressor(void *state) { - struct rtsp_state *sr; - sr = (struct rtsp_state *) state; + struct video_rtsp_state *sr; + sr = (struct video_rtsp_state *) state; - sr->vrtsp_state->sd = (struct state_decompress *) calloc(2, + sr->sd = (struct state_decompress *) calloc(2, sizeof(struct state_decompress *)); initialize_video_decompress(); if (decompress_is_available(LIBAVCODEC_MAGIC)) { - sr->vrtsp_state->sd = decompress_init(LIBAVCODEC_MAGIC); + sr->sd = decompress_init(LIBAVCODEC_MAGIC); - sr->vrtsp_state->des.width = sr->vrtsp_state->width; - sr->vrtsp_state->des.height = sr->vrtsp_state->height; - sr->vrtsp_state->des.color_spec = sr->vrtsp_state->frame->color_spec; - sr->vrtsp_state->des.tile_count = 0; - sr->vrtsp_state->des.interlacing = PROGRESSIVE; + sr->des.width = sr->width; + sr->des.height = sr->height; + sr->des.color_spec = sr->frame->color_spec; + sr->des.tile_count = 0; + sr->des.interlacing = PROGRESSIVE; - decompress_reconfigure(sr->vrtsp_state->sd, sr->vrtsp_state->des, 16, 8, 0, - vc_get_linesize(sr->vrtsp_state->des.width, UYVY), UYVY); + decompress_reconfigure(sr->sd, sr->des, 16, 8, 0, + vc_get_linesize(sr->des.width, UYVY), UYVY); } else return 0; - sr->vrtsp_state->out_frame = malloc(sr->vrtsp_state->width * sr->vrtsp_state->height * 4); + sr->out_frame = malloc(sr->width * sr->height * 4); return 1; } @@ -1021,126 +987,6 @@ get_sdp_filename(const char *url, char *sdp_filename) { } } -/** - * scan sdp file for media control attribute - */ -static void -check_and_set_media_control_attribute(const char *sdp_filename, void *state) { - struct rtsp_state *rtspState; - rtspState = (struct rtsp_state *) state; - - int max_len = 1256; - char *s = malloc(max_len); - - char *track = malloc(max_len); - char *track_ant = malloc(max_len); - printf("\n\n"); - FILE *sdp_fp = fopen(sdp_filename, "rt"); - //control[0] = '\0'; - if (sdp_fp != NULL) { - while (fgets(s, max_len - 2, sdp_fp) != NULL) { - printf("\nSDP: %s\n",s); - sscanf(s, " a = control: %s", track_ant); - if (strcmp(track_ant, "") != 0) { - track = strstr(track_ant, "track"); - if (track != NULL) - break; - } - } - printf("\n\n"); - fclose(sdp_fp); - } - free(s); - memcpy(rtspState->vrtsp_state->control, track, strlen(track)); -} - -static void -get_media_control_attribute(const char *sdp_filename, char *control) { - int max_len = 1256; - char *s = malloc(max_len); - - char *track = malloc(max_len); - char *track_ant = malloc(max_len); - printf("\n\n"); - FILE *sdp_fp = fopen(sdp_filename, "rt"); - //control[0] = '\0'; - if (sdp_fp != NULL) { - while (fgets(s, max_len - 2, sdp_fp) != NULL) { - printf("\nSDP: %s\n",s); - sscanf(s, " a = control: %s", track_ant); - if (strcmp(track_ant, "") != 0) { - track = strstr(track_ant, "track"); - if (track != NULL) - break; - } - } - printf("\n\n"); - fclose(sdp_fp); - } - free(s); - memcpy(control, track, strlen(track)); -} - -/** - * scan sdp file for incoming codec and set it - */ -static char * -set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state) { - struct rtsp_state *sr; - sr = (struct rtsp_state *) state; - - int max_len = 1256; - char *pt = malloc(4 * sizeof(char *)); - char *codec = malloc(32 * sizeof(char *)); - char *s = malloc(max_len); - FILE *sdp_fp = fopen(sdp_filename, "rt"); - - if (sdp_fp != NULL) { - while (fgets(s, max_len - 2, sdp_fp) != NULL) { - sscanf(s, " m = video 0 RTP/AVP %s", pt); - } - fclose(sdp_fp); - } - free(s); - - s = malloc(max_len); - sdp_fp = fopen(sdp_filename, "rt"); - - if (sdp_fp != NULL) { - while (fgets(s, max_len - 2, sdp_fp) != NULL) { - sscanf(s, " a=rtpmap:96 %s", codec); - } - fclose(sdp_fp); - } - free(s); - - char *save_ptr = NULL; - char *tmp; - tmp = strtok_r(codec, "/", &save_ptr); - if (!tmp) { - fprintf(stderr, "[rtsp] no codec atribute found into sdp file...\n"); - return NULL; - } - - printf("\n\nCODEC = %s\n\n",tmp); - - sprintf((char *) sr->vrtsp_state->in_codec, "%s", tmp); - - if (memcmp(sr->vrtsp_state->in_codec, "H264", 4) == 0){ - sr->vrtsp_state->frame->color_spec = H264; - return "H264"; - } - else if (memcmp(sr->vrtsp_state->in_codec, "VP8", 3) == 0){ - sr->vrtsp_state->frame->color_spec = VP8; - return "VP8"; - } - else{ - sr->vrtsp_state->frame->color_spec = RGBA; - return "RGBA"; - } - return NULL; -} - struct vidcap_type * vidcap_rtsp_probe(void) { struct vidcap_type *vt; From 13337ee1f56b666bc652b224727eee7d1bc7876c Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 3 Feb 2014 09:25:48 +0100 Subject: [PATCH 13/57] add internal header method for rtsp client --- src/video_capture/rtsp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 7543d4668..adb93ec17 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -132,6 +132,8 @@ set_codec_attribute_from_incoming_media(const char *sdp_filename, void *state); static int get_nals(const char *sdp_filename, char *nals); +void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state); + static int init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals); From e0fb6a3db72b08940c4a8a7acc42d30131f2009b Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Wed, 12 Feb 2014 09:54:50 +0100 Subject: [PATCH 14/57] rtsp server issue solved, now reinits with any possible request working --- configure.ac | 5 ++-- src/rtp/rtpdec_h264.c | 5 ++++ src/rtsp/BasicRTSPOnlySubsession.cpp | 34 ++++++++++++++++++---------- src/sender.c | 9 ++++++-- src/video_capture/rtsp.c | 4 ++-- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index 9f09ca844..4c06d7a15 100644 --- a/configure.ac +++ b/configure.ac @@ -1280,6 +1280,7 @@ AC_SUBST(RTSP_OBJ) # ------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------- # RTSP server stuff +# TODO: create pkg-config search path for liblivemedia-dev (create live555.pc file) # ------------------------------------------------------------------------------------------------- RTSP_SERVER_INC= RTSP_SERVER_LIB= @@ -1303,9 +1304,9 @@ case $host in then AC_DEFINE([HAVE_RTSP_SERVER], [1], [RTSP server build with live555 support]) SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" + CFLAGS="$CFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" SAVED_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" + CXXFLAGS="$CXXFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" RTSP_SERVER_INC= RTSP_SERVER_LIB="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock" RTSP_SERVER_OBJ="src/rtsp/c_basicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlySubsession.o" diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index 0b5731b55..f49c585fd 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -92,6 +92,11 @@ int decode_frame_h264(struct coded_data *cdata, void *rx_data) { type = nal & 0x1f; nri = nal & 0x60; + //TODO CHECK WxH! AND REFACTOR TYPE CHECKING +// if (type == 7){ +// fill_coded_frame_from_sps(frame, (unsigned char*) pckt->data, &pckt->data_len); +// } + if (type >= 1 && type <= 23) { if (buffers->bframe && !(type == 1 && nri == 0)){ buffers->bframe = FALSE; diff --git a/src/rtsp/BasicRTSPOnlySubsession.cpp b/src/rtsp/BasicRTSPOnlySubsession.cpp index 31bf37940..722572455 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.cpp +++ b/src/rtsp/BasicRTSPOnlySubsession.cpp @@ -205,15 +205,13 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, unsigned& rtpTimestamp, ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler, void* serverRequestAlternativeByteHandlerClientData) { + struct response *resp = NULL; - if ((Vdestination == NULL && Adestination == NULL)){ - return; - } else{ - struct response *resp = NULL; - char pathV[1024]; - char pathA[1024]; + if (Vdestination != NULL){ + + if(avType == 1){ + char pathV[1024]; - if(avType == 1 && Vdestination != NULL){ memset(pathV, 0, sizeof(pathV)); enum module_class path_sender[] = { MODULE_CLASS_SENDER, MODULE_CLASS_NONE }; append_message_path(pathV, sizeof(pathV), path_sender); @@ -237,7 +235,13 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, resp = send_message(fmod, pathV, (struct message *) msgV2); resp = NULL; } - if(avType == 2 && Adestination != NULL){ + } + + if(Adestination != NULL){ + + if(avType == 2){ + char pathA[1024]; + struct msg_sender *msg = (struct msg_sender *) new_message(sizeof(struct msg_sender)); memset(pathA, 0, sizeof(pathA)); @@ -267,13 +271,11 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, } void BasicRTSPOnlySubsession::deleteStream(unsigned clientSessionId, void*& streamToken){ - if ((Vdestination == NULL && Adestination == NULL)){ - return; + if (Vdestination == NULL){ + } else { char pathV[1024]; - char pathA[1024]; Vdestination = NULL; - Adestination = NULL; if(avType == 1 || Vdestination != NULL){ memset(pathV, 0, sizeof(pathV)); @@ -295,6 +297,14 @@ void BasicRTSPOnlySubsession::deleteStream(unsigned clientSessionId, void*& stre msgV2->type = SENDER_MSG_CHANGE_RECEIVER; send_message(fmod, pathV, (struct message *) msgV2); } + } + + if(Adestination == NULL){ + + } else { + char pathA[1024]; + Adestination = NULL; + if(avType == 2 || Adestination != NULL){ memset(pathA, 0, sizeof(pathA)); enum module_class path_sender[] = { MODULE_CLASS_AUDIO, MODULE_CLASS_SENDER, MODULE_CLASS_NONE }; diff --git a/src/sender.c b/src/sender.c index 052963744..7a9f4f6b8 100644 --- a/src/sender.c +++ b/src/sender.c @@ -140,9 +140,14 @@ static void sender_process_external_message(struct sender_data *data, struct msg } break; case SENDER_MSG_CHANGE_PORT: - ((struct ultragrid_rtp_state *) - data->tx_module_state)->network_devices + if(data->rxtx_protocol == ULTRAGRID_RTP){ + ((struct ultragrid_rtp_state *)data->tx_module_state)->network_devices = change_tx_port(data->uv, msg->port); + }else if(data->rxtx_protocol == H264_STD){ + ((struct h264_rtp_state *)data->tx_module_state)->network_devices + = change_tx_port(data->uv, msg->port); + } + break; case SENDER_MSG_PAUSE: data->priv->paused = true; diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index adb93ec17..1f2a4ea48 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -83,14 +83,14 @@ if ((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK){ \ fprintf(stderr, "[rtsp error] curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ -exit(0); \ +return NULL; \ } #define my_curl_easy_perform(A) \ if ((res = curl_easy_perform((A))) != CURLE_OK){ \ fprintf(stderr, "[rtsp error] curl_easy_perform(%s) failed: %d\n", #A, res); \ printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ -exit(0); \ +return NULL; \ } /* send RTSP GET_PARAMETERS request */ From 88657442b5d72ec6448d5f33083172523504d3c7 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 14 Feb 2014 14:00:33 +0100 Subject: [PATCH 15/57] rtsp server issue solved --- src/main.c | 3 ++- src/rtsp/BasicRTSPOnlySubsession.cpp | 36 +++++++++++----------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/main.c b/src/main.c index 0ab38c734..3e5e966b2 100644 --- a/src/main.c +++ b/src/main.c @@ -1434,7 +1434,8 @@ int main(int argc, char *argv[]) uint8_t avType; if(strcmp("none", vidcap_params_get_driver(vidcap_params_head)) != 0 && (strcmp("none",audio_send) != 0)) avType = 0; //AVStream else if((strcmp("none",audio_send) != 0)) avType = 2; //AStream - else avType = 1; //VStream + else if(strcmp("none", vidcap_params_get_driver(vidcap_params_head))) avType = 1; //VStream + else printf("[RTSP SERVER] no stream type... check capture devices input\n"); rtsp_server = init_rtsp_server(0, &root_mod, avType); //port, root_module, avType c_start_server(rtsp_server); #endif diff --git a/src/rtsp/BasicRTSPOnlySubsession.cpp b/src/rtsp/BasicRTSPOnlySubsession.cpp index 722572455..03198c912 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.cpp +++ b/src/rtsp/BasicRTSPOnlySubsession.cpp @@ -89,7 +89,7 @@ void BasicRTSPOnlySubsession ::setSDPLines() { //TODO: should be more dynamic //VStream - if(avType == 1){ + if(avType == 1 || avType == 0){ unsigned estBitrate = 5000; char const* mediaType = "video"; uint8_t rtpPayloadType = 96; @@ -123,7 +123,7 @@ void BasicRTSPOnlySubsession fSDPLines = sdpLines; } //AStream - if(avType == 2){ + if(avType == 2 || avType == 0){ unsigned estBitrate = 384; char const* mediaType = "audio"; uint8_t rtpPayloadType = 97; @@ -172,7 +172,7 @@ void BasicRTSPOnlySubsession::getStreamParameters(unsigned clientSessionId, Port& serverRTCPPort, void*& streamToken) { - if(Vdestination == NULL && avType == 1){ + if(Vdestination == NULL && (avType == 1 || avType == 0)){ if (fSDPLines == NULL){ setSDPLines(); } @@ -183,7 +183,7 @@ void BasicRTSPOnlySubsession::getStreamParameters(unsigned clientSessionId, destinationAddr.s_addr = destinationAddress; Vdestination = new Destinations(destinationAddr, clientRTPPort,clientRTCPPort); } - if(Adestination == NULL && avType == 2){ + if(Adestination == NULL && (avType == 2 || avType == 0)){ if (fSDPLines == NULL){ setSDPLines(); } @@ -208,8 +208,7 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, struct response *resp = NULL; if (Vdestination != NULL){ - - if(avType == 1){ + if(avType == 1 || avType == 0){ char pathV[1024]; memset(pathV, 0, sizeof(pathV)); @@ -238,8 +237,7 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, } if(Adestination != NULL){ - - if(avType == 2){ + if(avType == 2 || avType == 0){ char pathA[1024]; struct msg_sender *msg = (struct msg_sender *) @@ -271,13 +269,10 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, } void BasicRTSPOnlySubsession::deleteStream(unsigned clientSessionId, void*& streamToken){ - if (Vdestination == NULL){ - - } else { - char pathV[1024]; - Vdestination = NULL; - - if(avType == 1 || Vdestination != NULL){ + if (Vdestination != NULL){ + if(avType == 1 || avType == 0){ + char pathV[1024]; + Vdestination = NULL; memset(pathV, 0, sizeof(pathV)); enum module_class path_sender[] = { MODULE_CLASS_SENDER, MODULE_CLASS_NONE }; append_message_path(pathV, sizeof(pathV), path_sender); @@ -299,13 +294,10 @@ void BasicRTSPOnlySubsession::deleteStream(unsigned clientSessionId, void*& stre } } - if(Adestination == NULL){ - - } else { - char pathA[1024]; - Adestination = NULL; - - if(avType == 2 || Adestination != NULL){ + if(Adestination != NULL){ + if(avType == 2 || avType == 0){ + char pathA[1024]; + Adestination = NULL; memset(pathA, 0, sizeof(pathA)); enum module_class path_sender[] = { MODULE_CLASS_AUDIO, MODULE_CLASS_SENDER, MODULE_CLASS_NONE }; append_message_path(pathA, sizeof(pathA), path_sender); From fea38e301128c92a1c497c36fa4f132a02b9b5d6 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 14 Feb 2014 14:29:27 +0100 Subject: [PATCH 16/57] set reclamationTestSeconds to check client lost connection before 25seconds, it can be configured at basicRTSPOnlyServer.cpp --- src/rtsp/BasicRTSPOnlyServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rtsp/BasicRTSPOnlyServer.cpp b/src/rtsp/BasicRTSPOnlyServer.cpp index 7f99c0dfb..afcd77c3f 100644 --- a/src/rtsp/BasicRTSPOnlyServer.cpp +++ b/src/rtsp/BasicRTSPOnlyServer.cpp @@ -81,6 +81,8 @@ int BasicRTSPOnlyServer::init_server() { if (env != NULL || rtspServer != NULL || mod == NULL || (avType > 2 && avType < 0)){ exit(1); } + //setting livenessTimeoutTask + unsigned reclamationTestSeconds = 25; TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); @@ -98,7 +100,7 @@ int BasicRTSPOnlyServer::init_server() { fPort = 8554; } - rtspServer = RTSPServer::createNew(*env, fPort, authDB); + rtspServer = RTSPServer::createNew(*env, fPort, authDB, reclamationTestSeconds); if (rtspServer == NULL) { *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; exit(1); From 72095f6c1677faa42a5d3b4ed36bc529b440d585 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 17 Feb 2014 17:44:28 +0100 Subject: [PATCH 17/57] huge refactor of rtsp client, now dinamically WxH re/configuration --- configure.ac | 2 +- src/rtp/pbuf.c | 127 ++++++++---- src/rtp/rtpdec_h264.c | 304 ++++++++++++++++++---------- src/rtp/rtpdec_h264.h | 12 +- src/types.h | 26 ++- src/utils/bs.h | 388 +++++++++++++++++++++++++++++++++++ src/utils/h264_stream.c | 426 +++++++++++++++++++++++++++++++++++++++ src/utils/h264_stream.h | 165 +++++++++++++++ src/video_capture/rtsp.c | 369 ++++++++++++++++++++------------- 9 files changed, 1510 insertions(+), 309 deletions(-) create mode 100644 src/utils/bs.h create mode 100644 src/utils/h264_stream.c create mode 100644 src/utils/h264_stream.h diff --git a/configure.ac b/configure.ac index 1de3420dc..62f94bbb5 100644 --- a/configure.ac +++ b/configure.ac @@ -1254,7 +1254,7 @@ case $host in CXXFLAGS="$CXXFLAGS ${GLIB_CFLAGS} ${CURL_CFLAGS}" RTSP_INC= RTSP_LIB="${GLIB_LIBS} ${CURL_LIBS}" - RTSP_OBJ="src/video_capture/rtsp.o src/rtp/rtpdec_h264.o" + RTSP_OBJ="src/utils/h264_stream.o src/video_capture/rtsp.o src/rtp/rtpdec_h264.o" AC_SUBST(RTSP_LIB_TARGET, "lib/ultragrid/vidcap_rtsp.so.$video_capture_abi_version") LIB_TARGETS="$LIB_TARGETS $RTSP_LIB_TARGET" LIB_OBJS="$LIB_OBJS $RTSP_OBJ" diff --git a/src/rtp/pbuf.c b/src/rtp/pbuf.c index e3f5a57a3..7b4179be5 100644 --- a/src/rtp/pbuf.c +++ b/src/rtp/pbuf.c @@ -91,6 +91,7 @@ struct pbuf { double deletion_delay; }; +static void free_cdata(struct coded_data *head); /*********************************************************************************/ static void pbuf_validate(struct pbuf *playout_buf) @@ -167,31 +168,60 @@ struct pbuf *pbuf_init(void) static void add_coded_unit(struct pbuf_node *node, rtp_packet * pkt) { - /* Add "pkt" to the frame represented by "node". The "node" has */ - /* previously been created, and has some coded data already... */ + /* Add "pkt" to the frame represented by "node". The "node" has */ + /* previously been created, and has some coded data already... */ - /* New arrivals are added at the head of the list, which is stored */ - /* in descending order of packets as they arrive (NOT necessarily */ - /* descending sequence number order, as the network might reorder) */ + /* New arrivals are added at the head of the list, which is stored */ + /* in descending order of packets as they arrive (NOT necessarily */ + /* descending sequence number order, as the network might reorder) */ - struct coded_data *tmp; + struct coded_data *tmp, *curr, *prv; - assert(node->rtp_timestamp == pkt->ts); - assert(node->cdata != NULL); + assert(node->rtp_timestamp == pkt->ts); + assert(node->cdata != NULL); - tmp = malloc(sizeof(struct coded_data)); - if (tmp != NULL) { - tmp->seqno = pkt->seq; - tmp->data = pkt; - tmp->prv = NULL; - tmp->nxt = node->cdata; - node->cdata->prv = tmp; - node->cdata = tmp; - node->mbit |= pkt->m; + tmp = malloc(sizeof(struct coded_data)); + if (tmp == NULL) { + /* this is bad, out of memory, drop the packet... */ + free(pkt); + return; + } + + tmp->seqno = pkt->seq; + tmp->data = pkt; + node->mbit |= pkt->m; + if((int16_t)(tmp->seqno - node->cdata->seqno) > 0){ + tmp->prv = NULL; + tmp->nxt = node->cdata; + node->cdata->prv = tmp; + node->cdata = tmp; + } else { + curr = node->cdata; + if (curr == NULL){ + /* this is bad, out of memory, drop the packet... */ + free(pkt); + free_cdata(tmp); } else { - /* this is bad, out of memory, drop the packet... */ + while (curr != NULL && ((int16_t)(tmp->seqno - curr->seqno) < 0)){ + prv = curr; + curr = curr->nxt; + } + if (curr == NULL) { + tmp->nxt = NULL; + tmp->prv = prv; + prv->nxt = tmp; + }else if ((int16_t)(tmp->seqno - curr->seqno) > 0){ + tmp->nxt = curr; + tmp->prv = curr->prv; + tmp->prv->nxt = tmp; + curr->prv = tmp; + } else { + /* this is bad, something went terribly wrong... */ free(pkt); + free_cdata(tmp); + } } + } } static struct pbuf_node *create_new_pnode(rtp_packet * pkt, double playout_delay, @@ -235,6 +265,7 @@ static struct pbuf_node *create_new_pnode(rtp_packet * pkt, double playout_delay void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt) { struct pbuf_node *tmp; + struct pbuf_node *curr; pbuf_validate(playout_buf); @@ -246,33 +277,43 @@ void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt) return; } - if (playout_buf->last->rtp_timestamp == pkt->ts) { - /* Packet belongs to last frame in playout_buf this is the */ - /* most likely scenario - although... */ - add_coded_unit(playout_buf->last, pkt); + if (playout_buf->last->rtp_timestamp < pkt->ts) { + /* Packet belongs to a new frame... */ + tmp = create_new_pnode(pkt, playout_buf->playout_delay, playout_buf->deletion_delay); + playout_buf->last->nxt = tmp; + tmp->prv = playout_buf->last; + playout_buf->last = tmp; } else { - if (playout_buf->last->rtp_timestamp < pkt->ts) { - /* Packet belongs to a new frame... */ - tmp = create_new_pnode(pkt, playout_buf->playout_delay, - playout_buf->deletion_delay); - playout_buf->last->nxt = tmp; - tmp->prv = playout_buf->last; - playout_buf->last = tmp; - } else { - /* Packet belongs to a previous frame... */ - if (playout_buf->frst->rtp_timestamp > pkt->ts) { - debug_msg("A very old packet - discarded\n"); - } else { - debug_msg - ("A packet for a previous frame, but might still be useful\n"); - /* Should probably insert this into the playout buffer here... */ - } - if (pkt->m) { - debug_msg - ("Oops... dropped packet with M bit set\n"); - } - free(pkt); + /* Packet belongs to a previous frame... */ + curr = playout_buf->last; + while(curr != playout_buf->frst && curr->rtp_timestamp > pkt->ts){ + curr = curr->prv; + } + + if (curr->rtp_timestamp == pkt->ts) { + /* Packet belongs to a previous existing frame... */ + add_coded_unit(curr, pkt); + } else if (curr->rtp_timestamp < pkt->ts){ + /* Packet belongs to a new previous frame */ + tmp = create_new_pnode(pkt, playout_buf->playout_delay,playout_buf->deletion_delay); + tmp->nxt = curr->nxt; + tmp->prv = curr; + curr->nxt->prv = tmp; + curr->nxt = tmp; + } else if (curr == playout_buf->frst) { + tmp = create_new_pnode(pkt, playout_buf->playout_delay,playout_buf->deletion_delay); + tmp->nxt = playout_buf->frst; + curr->prv = tmp; + playout_buf->frst = tmp; + + } else { + + if (pkt->m) { + debug_msg + ("Oops... dropped packet with M bit set\n"); } + free(pkt); + } } pbuf_validate(playout_buf); } diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index 0b5731b55..708b5f417 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -50,12 +50,16 @@ #include "rtp/rtp_callback.h" #include "rtp/pbuf.h" #include "rtp/rtpdec_h264.h" +#include "utils/h264_stream.h" +#include "utils/bs.h" +#include "video_frame.h" static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; -int decode_frame_h264(struct coded_data *cdata, void *rx_data) { +int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len); + +int decode_frame_h264(struct coded_data *cdata, void *decode_data) { rtp_packet *pckt = NULL; - int substream = 0; struct coded_data *orig = cdata; uint8_t nal; @@ -65,19 +69,21 @@ int decode_frame_h264(struct coded_data *cdata, void *rx_data) { int pass; int total_length = 0; - char *dst = NULL; + unsigned char *dst = NULL; int src_len; - struct std_frame_received *buffers = (struct std_frame_received *) rx_data; + struct video_frame *frame = (struct video_frame *)decode_data; + frame->h264_frame_type = BFRAME; for (pass = 0; pass < 2; pass++) { if (pass > 0) { cdata = orig; - buffers->buffer_len = total_length; - dst = buffers->frame_buffer + total_length; - buffers->bframe = TRUE; - buffers->iframe = FALSE; + if(frame->h264_frame_type == INTRA){ + total_length+=frame->h264_offset_len; + } + frame->h264_buffer_len = total_length; + dst = frame->h264_buffer + total_length; } while (cdata != NULL) { @@ -92,132 +98,133 @@ int decode_frame_h264(struct coded_data *cdata, void *rx_data) { type = nal & 0x1f; nri = nal & 0x60; + if (type == 7){ + fill_coded_frame_from_sps(frame, (unsigned char*) pckt->data, pckt->data_len); + } + if (type >= 1 && type <= 23) { - if (buffers->bframe && !(type == 1 && nri == 0)){ - buffers->bframe = FALSE; - } - if (!buffers->iframe && type == 5 ){ - buffers->iframe =TRUE; + if(frame->h264_frame_type != INTRA && (type == 5 || type == 6)) { + frame->h264_frame_type = INTRA; + } else if (frame->h264_frame_type == BFRAME && nri != 0){ + frame->h264_frame_type = OTHER; } + type = 1; } const uint8_t *src = NULL; switch (type) { - case 0: - case 1: - if (pass == 0) { - debug_msg("NAL type 1\n"); - total_length += sizeof(start_sequence) + pckt->data_len; - } else { - dst -= pckt->data_len + sizeof(start_sequence); - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), pckt->data, pckt->data_len); - unsigned char *dst2 = (unsigned char *)dst; - } - break; - case 24: - src = (const uint8_t *) pckt->data; - src_len = pckt->data_len; - - src++; - src_len--; - - while (src_len > 2) { - //TODO: Not properly tested - //TODO: bframes and iframes detection - uint16_t nal_size; - memcpy(&nal_size, src, sizeof(uint16_t)); - - src += 2; - src_len -= 2; - - if (nal_size <= src_len) { - if (pass == 0) { - total_length += sizeof(start_sequence) + nal_size; - } else { - dst -= nal_size + sizeof(start_sequence); - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), src, nal_size); - } + case 0: + case 1: + if (pass == 0) { + debug_msg("NAL type 1\n"); + total_length += sizeof(start_sequence) + pckt->data_len; } else { - error_msg("NAL size exceeds length: %u %d\n", nal_size, src_len); - return FALSE; + dst -= pckt->data_len + sizeof(start_sequence); + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), pckt->data, pckt->data_len); } - src += nal_size; - src_len -= nal_size; + break; + case 24: + src = (const uint8_t *) pckt->data; + src_len = pckt->data_len; - if (src_len < 0) { - error_msg("Consumed more bytes than we got! (%d)\n", src_len); - return FALSE; + src++; + src_len--; + + while (src_len > 2) { + //TODO: Not properly tested + //TODO: bframes and iframes detection + uint16_t nal_size; + memcpy(&nal_size, src, sizeof(uint16_t)); + + src += 2; + src_len -= 2; + + if (nal_size <= src_len) { + if (pass == 0) { + total_length += sizeof(start_sequence) + nal_size; + } else { + dst -= nal_size + sizeof(start_sequence); + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), src, nal_size); + } + } else { + error_msg("NAL size exceeds length: %u %d\n", nal_size, src_len); + return FALSE; + } + src += nal_size; + src_len -= nal_size; + + if (src_len < 0) { + error_msg("Consumed more bytes than we got! (%d)\n", src_len); + return FALSE; + } } - } - break; + break; case 25: case 26: case 27: case 29: - error_msg("Unhandled NAL type\n"); - return FALSE; + error_msg("Unhandled NAL type\n"); + return FALSE; case 28: - src = (const uint8_t *) pckt->data; - src_len = pckt->data_len; + src = (const uint8_t *) pckt->data; + src_len = pckt->data_len; - src++; - src_len--; - - if (src_len > 1) { - uint8_t fu_header = *src; - uint8_t start_bit = fu_header >> 7; - //uint8_t end_bit = (fu_header & 0x40) >> 6; - uint8_t nal_type = fu_header & 0x1f; - uint8_t reconstructed_nal; - - if (buffers->bframe && !(nal_type == 1 && nri == 0)){ - buffers->bframe = FALSE; - } - - if (!buffers->iframe && nal_type == 5){ - buffers->iframe = TRUE; - } - - // Reconstruct this packet's true nal; only the data follows. - /* The original nal forbidden bit and NRI are stored in this - * packet's nal. */ - reconstructed_nal = nal & 0xe0; - reconstructed_nal |= nal_type; - - // skip the fu_header src++; src_len--; - if (pass == 0) { - if (start_bit) { - total_length += sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; + if (src_len > 1) { + uint8_t fu_header = *src; + uint8_t start_bit = fu_header >> 7; + //uint8_t end_bit = (fu_header & 0x40) >> 6; + uint8_t nal_type = fu_header & 0x1f; + uint8_t reconstructed_nal; + + if(frame->h264_frame_type != INTRA && (nal_type == 5 || nal_type == 6)){ + frame->h264_frame_type = INTRA; + } else if (frame->h264_frame_type == BFRAME && nri != 0){ + frame->h264_frame_type = OTHER; + } + + // Reconstruct this packet's true nal; only the data follows. + /* The original nal forbidden bit and NRI are stored in this + * packet's nal. */ + reconstructed_nal = nal & 0xe0; + reconstructed_nal |= nal_type; + + // skip the fu_header + src++; + src_len--; + + if (pass == 0) { + if (start_bit) { + total_length += sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; + } else { + total_length += src_len; + } } else { - total_length += src_len; + if (start_bit) { + dst -= sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; + memcpy(dst, start_sequence, sizeof(start_sequence)); + memcpy(dst + sizeof(start_sequence), &reconstructed_nal, sizeof(reconstructed_nal)); + memcpy(dst + sizeof(start_sequence) + sizeof(reconstructed_nal), src, src_len); + } else { + dst -= src_len; + memcpy(dst, src, src_len); + } } } else { - if (start_bit) { - dst -= sizeof(start_sequence) + sizeof(reconstructed_nal) + src_len; - memcpy(dst, start_sequence, sizeof(start_sequence)); - memcpy(dst + sizeof(start_sequence), &reconstructed_nal, sizeof(reconstructed_nal)); - memcpy(dst + sizeof(start_sequence) + sizeof(reconstructed_nal), src, src_len); - } else { - dst -= src_len; - memcpy(dst, src, src_len); - } + error_msg("Too short data for FU-A H264 RTP packet\n"); + return FALSE; } - } else { - error_msg("Too short data for FU-A H264 RTP packet\n"); - return FALSE; - } - break; + break; default: - error_msg("Unknown NAL type\n"); - return FALSE; + error_msg("Unknown NAL type\n"); + return FALSE; } cdata = cdata->nxt; } @@ -225,3 +232,86 @@ int decode_frame_h264(struct coded_data *cdata, void *rx_data) { return TRUE; } + +int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len){ + uint32_t width, height; + sps_t* sps = (sps_t*)malloc(sizeof(sps_t)); + uint8_t* rbsp_buf = (uint8_t*)malloc(data_len); + if (nal_to_rbsp(data, &data_len, rbsp_buf, &data_len) < 0){ + free(rbsp_buf); + free(sps); + return -1; + } + bs_t* b = bs_new(rbsp_buf, data_len); + if(read_seq_parameter_set_rbsp(sps,b) < 0){ + bs_free(b); + free(rbsp_buf); + free(sps); + return -1; + } + width = (sps->pic_width_in_mbs_minus1 + 1) * 16; + height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16; + //NOTE: frame_mbs_only_flag = 1 --> only progressive frames + // frame_mbs_only_flag = 0 --> some type of interlacing (there are 3 types contemplated in the standard) + if (sps->frame_cropping_flag){ + width -= (sps->frame_crop_left_offset*2 + sps->frame_crop_right_offset*2); + height -= (sps->frame_crop_top_offset*2 + sps->frame_crop_bottom_offset*2); + } + + if((width != rx_data->h264_width) || (height != rx_data->h264_height)) { + rx_data->h264_width = width; + rx_data->h264_height = height; + vf_get_tile(rx_data, 0)->width = width; + vf_get_tile(rx_data, 0)->height = height; +// free(rx_data->tiles[0].data); +// rx_data->tiles[0].data = calloc(1, rx_data->h264_width * rx_data->h264_height); + } + + bs_free(b); + free(rbsp_buf); + free(sps); + + return 0; +} + +int width_height_from_SDP(int *widthOut, int *heightOut , unsigned char *data, int data_len){ + uint32_t width, height; + sps_t* sps = (sps_t*)malloc(sizeof(sps_t)); + uint8_t* rbsp_buf = (uint8_t*)malloc(data_len); + if (nal_to_rbsp(data, &data_len, rbsp_buf, &data_len) < 0){ + free(rbsp_buf); + free(sps); + return -1; + } + bs_t* b = bs_new(rbsp_buf, data_len); + if(read_seq_parameter_set_rbsp(sps,b) < 0){ + bs_free(b); + free(rbsp_buf); + free(sps); + return -1; + } + width = (sps->pic_width_in_mbs_minus1 + 1) * 16; + height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16; + //NOTE: frame_mbs_only_flag = 1 --> only progressive frames + // frame_mbs_only_flag = 0 --> some type of interlacing (there are 3 types contemplated in the standard) + if (sps->frame_cropping_flag){ + width -= (sps->frame_crop_left_offset*2 + sps->frame_crop_right_offset*2); + height -= (sps->frame_crop_top_offset*2 + sps->frame_crop_bottom_offset*2); + } + + debug_msg("\n\n[width_height_from_SDP] width: %d height: %d\n\n",width,height); + + + if(width > 0){ + *widthOut = width; + } + if(height > 0){ + *heightOut = height; + } + + bs_free(b); + free(rbsp_buf); + free(sps); + + return 0; +} diff --git a/src/rtp/rtpdec_h264.h b/src/rtp/rtpdec_h264.h index 61b7c6352..9e9cf02bb 100644 --- a/src/rtp/rtpdec_h264.h +++ b/src/rtp/rtpdec_h264.h @@ -44,15 +44,7 @@ #ifndef _RTP_DEC_H264_H #define _RTP_DEC_H264_H -struct std_frame_received { - uint32_t buffer_len; //[MAX_SUBSTREAMS]; - //uint32_t buffer_num;//[MAX_SUBSTREAMS]; - char *frame_buffer; //[MAX_SUBSTREAMS]; - uint8_t bframe; - uint8_t iframe; -}; - -int -decode_frame_h264(struct coded_data *cdata, void *rx_data); +int decode_frame_h264(struct coded_data *cdata, void *decode_data); +int width_height_from_SDP(int *widthOut, int *heightOut , unsigned char *data, int data_len); #endif diff --git a/src/types.h b/src/types.h index 15258fc5e..475c75c1a 100644 --- a/src/types.h +++ b/src/types.h @@ -113,6 +113,12 @@ struct video_desc { unsigned int tile_count; }; +typedef enum h264_frame_type { + INTRA, + BFRAME, + OTHER +} h264_frame_type_t; + /** * @brief Struct video_frame represents a video frame and contains video description. */ @@ -156,11 +162,21 @@ struct video_frame { //standard transport uint8_t isStd; - //h264_params - uint8_t h264_bframe; - uint8_t h264_iframe; - int h264_width; - int h264_height; + //H264 Standard transport + // Config + unsigned int h264_width; + unsigned int h264_height; + codec_t codec; + // Data + unsigned char *h264_buffer; + unsigned int h264_buffer_len; + unsigned int h264_offset_len; + unsigned char *h264_offset_buffer; + // Stats + unsigned int h264_media_time; + unsigned int h264_seqno; + // Control + h264_frame_type_t h264_frame_type; }; /** diff --git a/src/utils/bs.h b/src/utils/bs.h new file mode 100644 index 000000000..c5087cdea --- /dev/null +++ b/src/utils/bs.h @@ -0,0 +1,388 @@ +/* + * h264bitstream - a library for reading and writing H.264 video + * Copyright (C) 2005-2007 Auroras Entertainment, LLC + * Copyright (C) 2008-2011 Avail-TVN + * + * Written by Alex Izvorski and Alex Giladi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _H264_BS_H +#define _H264_BS_H 1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t* start; + uint8_t* p; + uint8_t* end; + int bits_left; +} bs_t; + +#define _OPTIMIZE_BS_ 1 + +#if ( _OPTIMIZE_BS_ > 0 ) +#ifndef FAST_U8 +#define FAST_U8 +#endif +#endif + + +static bs_t* bs_new(uint8_t* buf, size_t size); +static void bs_free(bs_t* b); +static bs_t* bs_clone( bs_t* dest, const bs_t* src ); +static bs_t* bs_init(bs_t* b, uint8_t* buf, size_t size); +static uint32_t bs_byte_aligned(bs_t* b); +static int bs_eof(bs_t* b); +static int bs_overrun(bs_t* b); +static int bs_pos(bs_t* b); + +static uint32_t bs_peek_u1(bs_t* b); +static uint32_t bs_read_u1(bs_t* b); +static uint32_t bs_read_u(bs_t* b, int n); +static uint32_t bs_read_f(bs_t* b, int n); +static uint32_t bs_read_u8(bs_t* b); +static uint32_t bs_read_ue(bs_t* b); +static int32_t bs_read_se(bs_t* b); + +static void bs_write_u1(bs_t* b, uint32_t v); +static void bs_write_u(bs_t* b, int n, uint32_t v); +static void bs_write_f(bs_t* b, int n, uint32_t v); +static void bs_write_u8(bs_t* b, uint32_t v); +static void bs_write_ue(bs_t* b, uint32_t v); +static void bs_write_se(bs_t* b, int32_t v); + +static int bs_read_bytes(bs_t* b, uint8_t* buf, int len); +static int bs_write_bytes(bs_t* b, uint8_t* buf, int len); +static int bs_skip_bytes(bs_t* b, int len); +static uint32_t bs_next_bits(bs_t* b, int nbits); +// IMPLEMENTATION + +static inline bs_t* bs_init(bs_t* b, uint8_t* buf, size_t size) +{ + b->start = buf; + b->p = buf; + b->end = buf + size; + b->bits_left = 8; + return b; +} + +static inline bs_t* bs_new(uint8_t* buf, size_t size) +{ + bs_t* b = (bs_t*)malloc(sizeof(bs_t)); + bs_init(b, buf, size); + return b; +} + +static inline void bs_free(bs_t* b) +{ + free(b); +} + +static inline bs_t* bs_clone(bs_t* dest, const bs_t* src) +{ + dest->start = src->p; + dest->p = src->p; + dest->end = src->end; + dest->bits_left = src->bits_left; + return dest; +} + +static inline uint32_t bs_byte_aligned(bs_t* b) +{ + return (b->bits_left == 8); +} + +static inline int bs_eof(bs_t* b) { if (b->p >= b->end) { return 1; } else { return 0; } } + +static inline int bs_overrun(bs_t* b) { if (b->p > b->end) { return 1; } else { return 0; } } + +static inline int bs_pos(bs_t* b) { if (b->p > b->end) { return (b->end - b->start); } else { return (b->p - b->start); } } + +static inline int bs_bytes_left(bs_t* b) { return (b->end - b->p); } + +static inline uint32_t bs_read_u1(bs_t* b) +{ + uint32_t r = 0; + + b->bits_left--; + + if (! bs_eof(b)) + { + r = ((*(b->p)) >> b->bits_left) & 0x01; + } + + if (b->bits_left == 0) { b->p ++; b->bits_left = 8; } + + return r; +} + +static inline void bs_skip_u1(bs_t* b) +{ + b->bits_left--; + if (b->bits_left == 0) { b->p ++; b->bits_left = 8; } +} + +static inline uint32_t bs_peek_u1(bs_t* b) +{ + uint32_t r = 0; + + if (! bs_eof(b)) + { + r = ((*(b->p)) >> ( b->bits_left - 1 )) & 0x01; + } + return r; +} + + +static inline uint32_t bs_read_u(bs_t* b, int n) +{ + uint32_t r = 0; + int i; + for (i = 0; i < n; i++) + { + r |= ( bs_read_u1(b) << ( n - i - 1 ) ); + } + return r; +} + +static inline void bs_skip_u(bs_t* b, int n) +{ + int i; + for ( i = 0; i < n; i++ ) + { + bs_skip_u1( b ); + } +} + +static inline uint32_t bs_read_f(bs_t* b, int n) { return bs_read_u(b, n); } + +static inline uint32_t bs_read_u8(bs_t* b) +{ +#ifdef FAST_U8 + if (b->bits_left == 8 && ! bs_eof(b)) // can do fast read + { + uint32_t r = b->p[0]; + b->p++; + return r; + } +#endif + return bs_read_u(b, 8); +} + +static inline uint32_t bs_read_ue(bs_t* b) +{ + int32_t r = 0; + int i = 0; + + while( (bs_read_u1(b) == 0) && (i < 32) && (!bs_eof(b)) ) + { + i++; + } + r = bs_read_u(b, i); + r += (1 << i) - 1; + return r; +} + +static inline int32_t bs_read_se(bs_t* b) +{ + int32_t r = bs_read_ue(b); + if (r & 0x01) + { + r = (r+1)/2; + } + else + { + r = -(r/2); + } + return r; +} + + +static inline void bs_write_u1(bs_t* b, uint32_t v) +{ + b->bits_left--; + + if (! bs_eof(b)) + { + // FIXME this is slow, but we must clear bit first + // is it better to memset(0) the whole buffer during bs_init() instead? + // if we don't do either, we introduce pretty nasty bugs + (*(b->p)) &= ~(0x01 << b->bits_left); + (*(b->p)) |= ((v & 0x01) << b->bits_left); + } + + if (b->bits_left == 0) { b->p ++; b->bits_left = 8; } +} + +static inline void bs_write_u(bs_t* b, int n, uint32_t v) +{ + int i; + for (i = 0; i < n; i++) + { + bs_write_u1(b, (v >> ( n - i - 1 ))&0x01 ); + } +} + +static inline void bs_write_f(bs_t* b, int n, uint32_t v) { bs_write_u(b, n, v); } + +static inline void bs_write_u8(bs_t* b, uint32_t v) +{ +#ifdef FAST_U8 + if (b->bits_left == 8 && ! bs_eof(b)) // can do fast write + { + b->p[0] = v; + b->p++; + return; + } +#endif + bs_write_u(b, 8, v); +} + +static inline void bs_write_ue(bs_t* b, uint32_t v) +{ + static const int len_table[256] = + { + 1, + 1, + 2,2, + 3,3,3,3, + 4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + }; + + int len; + + if (v == 0) + { + bs_write_u1(b, 1); + } + else + { + v++; + + if (v >= 0x01000000) + { + len = 24 + len_table[ v >> 24 ]; + } + else if(v >= 0x00010000) + { + len = 16 + len_table[ v >> 16 ]; + } + else if(v >= 0x00000100) + { + len = 8 + len_table[ v >> 8 ]; + } + else + { + len = len_table[ v ]; + } + + bs_write_u(b, 2*len-1, v); + } +} + +static inline void bs_write_se(bs_t* b, int32_t v) +{ + if (v <= 0) + { + bs_write_ue(b, -v*2); + } + else + { + bs_write_ue(b, v*2 - 1); + } +} + +static inline int bs_read_bytes(bs_t* b, uint8_t* buf, int len) +{ + int actual_len = len; + if (b->end - b->p < actual_len) { actual_len = b->end - b->p; } + if (actual_len < 0) { actual_len = 0; } + memcpy(buf, b->p, actual_len); + if (len < 0) { len = 0; } + b->p += len; + return actual_len; +} + +static inline int bs_write_bytes(bs_t* b, uint8_t* buf, int len) +{ + int actual_len = len; + if (b->end - b->p < actual_len) { actual_len = b->end - b->p; } + if (actual_len < 0) { actual_len = 0; } + memcpy(b->p, buf, actual_len); + if (len < 0) { len = 0; } + b->p += len; + return actual_len; +} + +static inline int bs_skip_bytes(bs_t* b, int len) +{ + int actual_len = len; + if (b->end - b->p < actual_len) { actual_len = b->end - b->p; } + if (actual_len < 0) { actual_len = 0; } + if (len < 0) { len = 0; } + b->p += len; + return actual_len; +} + +static inline uint32_t bs_next_bits(bs_t* bs, int nbits) +{ + bs_t b; + bs_clone(&b,bs); + return bs_read_u(&b, nbits); +} + +static inline uint64_t bs_next_bytes(bs_t* bs, int nbytes) +{ + int i = 0; + uint64_t val = 0; + + if ( (nbytes > 8) || (nbytes < 1) ) { return 0; } + if (bs->p + nbytes > bs->end) { return 0; } + + for ( i = 0; i < nbytes; i++ ) { val = ( val << 8 ) | bs->p[i]; } + return val; +} + +#define bs_print_state(b) fprintf( stderr, "%s:%d@%s: b->p=0x%02hhX, b->left = %d\n", __FILE__, __LINE__, __FUNCTION__, *b->p, b->bits_left ) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/h264_stream.c b/src/utils/h264_stream.c new file mode 100644 index 000000000..4538208ac --- /dev/null +++ b/src/utils/h264_stream.c @@ -0,0 +1,426 @@ +/* + * h264bitstream - a library for reading and writing H.264 video + * Copyright (C) 2005-2007 Auroras Entertainment, LLC + * Copyright (C) 2008-2011 Avail-TVN + * + * Written by Alex Izvorski and Alex Giladi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "h264_stream.h" + +/***************************** reading ******************************/ + +/** + Convert NAL data (Annex B format) to RBSP data. + The size of rbsp_buf must be the same as size of the nal_buf to guarantee the output will fit. + If that is not true, output may be truncated and an error will be returned. + Additionally, certain byte sequences in the input nal_buf are not allowed in the spec and also cause the conversion to fail and an error to be returned. + @param[in] nal_buf the nal data + @param[in,out] nal_size as input, pointer to the size of the nal data; as output, filled in with the actual size of the nal data + @param[in,out] rbsp_buf allocated memory in which to put the rbsp data + @param[in,out] rbsp_size as input, pointer to the maximum size of the rbsp data; as output, filled in with the actual size of rbsp data + @return actual size of rbsp data, or -1 on error + */ +// 7.3.1 NAL unit syntax +// 7.4.1.1 Encapsulation of an SODB within an RBSP +int nal_to_rbsp(const uint8_t* nal_buf, int* nal_size, uint8_t* rbsp_buf, int* rbsp_size) +{ + int i; + int j = 0; + int count = 0; + + for( i = 1; i < *nal_size; i++ ) + { + // in NAL unit, 0x000000, 0x000001 or 0x000002 shall not occur at any byte-aligned position + if( ( count == 2 ) && ( nal_buf[i] < 0x03) ) + { + return -1; + } + + if( ( count == 2 ) && ( nal_buf[i] == 0x03) ) + { + // check the 4th byte after 0x000003, except when cabac_zero_word is used, in which case the last three bytes of this NAL unit must be 0x000003 + if((i < *nal_size - 1) && (nal_buf[i+1] > 0x03)) + { + return -1; + } + + // if cabac_zero_word is used, the final byte of this NAL unit(0x03) is discarded, and the last two bytes of RBSP must be 0x0000 + if(i == *nal_size - 1) + { + break; + } + + i++; + count = 0; + } + + if ( j >= *rbsp_size ) + { + // error, not enough space + return -1; + } + + rbsp_buf[j] = nal_buf[i]; + if(nal_buf[i] == 0x00) + { + count++; + } + else + { + count = 0; + } + j++; + } + + *nal_size = i; + *rbsp_size = j; + return j; +} + +//7.3.2.1 Sequence parameter set RBSP syntax +int read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b) { + + int i; + + memset(sps, 0, sizeof(sps_t)); + + sps->profile_idc = bs_read_u8(b); + sps->constraint_set0_flag = bs_read_u1(b); + sps->constraint_set1_flag = bs_read_u1(b); + sps->constraint_set2_flag = bs_read_u1(b); + sps->constraint_set3_flag = bs_read_u1(b); + sps->constraint_set4_flag = bs_read_u1(b); + sps->constraint_set5_flag = bs_read_u1(b); + sps->reserved_zero_2bits = bs_read_u(b,2); /* all 0's */ + sps->level_idc = bs_read_u8(b); + sps->seq_parameter_set_id = bs_read_ue(b); + + sps->chroma_format_idc = 1; + if( sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 144 ) + { + sps->chroma_format_idc = bs_read_ue(b); + if( sps->chroma_format_idc == 3 ) + { + sps->residual_colour_transform_flag = bs_read_u1(b); + } + sps->bit_depth_luma_minus8 = bs_read_ue(b); + sps->bit_depth_chroma_minus8 = bs_read_ue(b); + sps->qpprime_y_zero_transform_bypass_flag = bs_read_u1(b); + sps->seq_scaling_matrix_present_flag = bs_read_u1(b); + if( sps->seq_scaling_matrix_present_flag ) + { + for( i = 0; i < 8; i++ ) + { + sps->seq_scaling_list_present_flag[ i ] = bs_read_u1(b); + if( sps->seq_scaling_list_present_flag[ i ] ) + { + if( i < 6 ) + { + read_scaling_list( b, sps->ScalingList4x4[ i ], 16, + sps->UseDefaultScalingMatrix4x4Flag[ i ]); + } + else + { + read_scaling_list( b, sps->ScalingList8x8[ i - 6 ], 64, + sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ); + } + } + } + } + } + sps->log2_max_frame_num_minus4 = bs_read_ue(b); + sps->pic_order_cnt_type = bs_read_ue(b); + if( sps->pic_order_cnt_type == 0 ) + { + sps->log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue(b); + } + else if( sps->pic_order_cnt_type == 1 ) + { + sps->delta_pic_order_always_zero_flag = bs_read_u1(b); + sps->offset_for_non_ref_pic = bs_read_se(b); + sps->offset_for_top_to_bottom_field = bs_read_se(b); + sps->num_ref_frames_in_pic_order_cnt_cycle = bs_read_ue(b); + for( i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++ ) + { + sps->offset_for_ref_frame[ i ] = bs_read_se(b); + } + } + sps->num_ref_frames = bs_read_ue(b); + sps->gaps_in_frame_num_value_allowed_flag = bs_read_u1(b); + sps->pic_width_in_mbs_minus1 = bs_read_ue(b); + sps->pic_height_in_map_units_minus1 = bs_read_ue(b); + sps->frame_mbs_only_flag = bs_read_u1(b); + if( !sps->frame_mbs_only_flag ) + { + sps->mb_adaptive_frame_field_flag = bs_read_u1(b); + } + sps->direct_8x8_inference_flag = bs_read_u1(b); + sps->frame_cropping_flag = bs_read_u1(b); + if( sps->frame_cropping_flag ) + { + sps->frame_crop_left_offset = bs_read_ue(b); + sps->frame_crop_right_offset = bs_read_ue(b); + sps->frame_crop_top_offset = bs_read_ue(b); + sps->frame_crop_bottom_offset = bs_read_ue(b); + } + sps->vui_parameters_present_flag = bs_read_u1(b); + if( sps->vui_parameters_present_flag ) + { + read_vui_parameters(sps, b); + } + read_rbsp_trailing_bits(b); + + return 0; +} + + +//7.3.2.1.1 Scaling list syntax +void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int useDefaultScalingMatrixFlag ) +{ + int j; + if(scalingList == NULL) + { + return; + } + + int lastScale = 8; + int nextScale = 8; + for( j = 0; j < sizeOfScalingList; j++ ) + { + if( nextScale != 0 ) + { + int delta_scale = bs_read_se(b); + nextScale = ( lastScale + delta_scale + 256 ) % 256; + useDefaultScalingMatrixFlag = ( j == 0 && nextScale == 0 ); + } + scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale; + lastScale = scalingList[ j ]; + } +} + +//Appendix E.1.1 VUI parameters syntax +void read_vui_parameters(sps_t* sps, bs_t* b) +{ + + sps->vui.aspect_ratio_info_present_flag = bs_read_u1(b); + if( sps->vui.aspect_ratio_info_present_flag ) + { + sps->vui.aspect_ratio_idc = bs_read_u8(b); + if( sps->vui.aspect_ratio_idc == SAR_Extended ) + { + sps->vui.sar_width = bs_read_u(b,16); + sps->vui.sar_height = bs_read_u(b,16); + } + } + sps->vui.overscan_info_present_flag = bs_read_u1(b); + if( sps->vui.overscan_info_present_flag ) + { + sps->vui.overscan_appropriate_flag = bs_read_u1(b); + } + sps->vui.video_signal_type_present_flag = bs_read_u1(b); + if( sps->vui.video_signal_type_present_flag ) + { + sps->vui.video_format = bs_read_u(b,3); + sps->vui.video_full_range_flag = bs_read_u1(b); + sps->vui.colour_description_present_flag = bs_read_u1(b); + if( sps->vui.colour_description_present_flag ) + { + sps->vui.colour_primaries = bs_read_u8(b); + sps->vui.transfer_characteristics = bs_read_u8(b); + sps->vui.matrix_coefficients = bs_read_u8(b); + } + } + sps->vui.chroma_loc_info_present_flag = bs_read_u1(b); + if( sps->vui.chroma_loc_info_present_flag ) + { + sps->vui.chroma_sample_loc_type_top_field = bs_read_ue(b); + sps->vui.chroma_sample_loc_type_bottom_field = bs_read_ue(b); + } + sps->vui.timing_info_present_flag = bs_read_u1(b); + if( sps->vui.timing_info_present_flag ) + { + sps->vui.num_units_in_tick = bs_read_u(b,32); + sps->vui.time_scale = bs_read_u(b,32); + sps->vui.fixed_frame_rate_flag = bs_read_u1(b); + } + sps->vui.nal_hrd_parameters_present_flag = bs_read_u1(b); + if( sps->vui.nal_hrd_parameters_present_flag ) + { + read_hrd_parameters(sps, b); + } + sps->vui.vcl_hrd_parameters_present_flag = bs_read_u1(b); + if( sps->vui.vcl_hrd_parameters_present_flag ) + { + read_hrd_parameters(sps, b); + } + if( sps->vui.nal_hrd_parameters_present_flag || sps->vui.vcl_hrd_parameters_present_flag ) + { + sps->vui.low_delay_hrd_flag = bs_read_u1(b); + } + sps->vui.pic_struct_present_flag = bs_read_u1(b); + sps->vui.bitstream_restriction_flag = bs_read_u1(b); + if( sps->vui.bitstream_restriction_flag ) + { + sps->vui.motion_vectors_over_pic_boundaries_flag = bs_read_u1(b); + sps->vui.max_bytes_per_pic_denom = bs_read_ue(b); + sps->vui.max_bits_per_mb_denom = bs_read_ue(b); + sps->vui.log2_max_mv_length_horizontal = bs_read_ue(b); + sps->vui.log2_max_mv_length_vertical = bs_read_ue(b); + sps->vui.num_reorder_frames = bs_read_ue(b); + sps->vui.max_dec_frame_buffering = bs_read_ue(b); + } +} + + +//Appendix E.1.2 HRD parameters syntax +void read_hrd_parameters(sps_t* sps, bs_t* b) +{ + int SchedSelIdx; + + sps->hrd.cpb_cnt_minus1 = bs_read_ue(b); + sps->hrd.bit_rate_scale = bs_read_u(b,4); + sps->hrd.cpb_size_scale = bs_read_u(b,4); + for( SchedSelIdx = 0; SchedSelIdx <= sps->hrd.cpb_cnt_minus1; SchedSelIdx++ ) + { + sps->hrd.bit_rate_value_minus1[ SchedSelIdx ] = bs_read_ue(b); + sps->hrd.cpb_size_value_minus1[ SchedSelIdx ] = bs_read_ue(b); + sps->hrd.cbr_flag[ SchedSelIdx ] = bs_read_u1(b); + } + sps->hrd.initial_cpb_removal_delay_length_minus1 = bs_read_u(b,5); + sps->hrd.cpb_removal_delay_length_minus1 = bs_read_u(b,5); + sps->hrd.dpb_output_delay_length_minus1 = bs_read_u(b,5); + sps->hrd.time_offset_length = bs_read_u(b,5); +} + +//7.3.2.11 RBSP trailing bits syntax +void read_rbsp_trailing_bits(bs_t* b) +{ + int rbsp_stop_one_bit = bs_read_u1( b ); // equal to 1 + + while( !bs_byte_aligned(b) ) + { + int rbsp_alignment_zero_bit = bs_read_u1( b ); // equal to 0 + } +} + +/***************************** debug ******************************/ + +void debug_sps(sps_t* sps) +{ + printf("======= SPS =======\n"); + printf(" profile_idc : %d \n", sps->profile_idc ); + printf(" constraint_set0_flag : %d \n", sps->constraint_set0_flag ); + printf(" constraint_set1_flag : %d \n", sps->constraint_set1_flag ); + printf(" constraint_set2_flag : %d \n", sps->constraint_set2_flag ); + printf(" constraint_set3_flag : %d \n", sps->constraint_set3_flag ); + printf(" constraint_set4_flag : %d \n", sps->constraint_set4_flag ); + printf(" constraint_set5_flag : %d \n", sps->constraint_set5_flag ); + printf(" reserved_zero_2bits : %d \n", sps->reserved_zero_2bits ); + printf(" level_idc : %d \n", sps->level_idc ); + printf(" seq_parameter_set_id : %d \n", sps->seq_parameter_set_id ); + printf(" chroma_format_idc : %d \n", sps->chroma_format_idc ); + printf(" residual_colour_transform_flag : %d \n", sps->residual_colour_transform_flag ); + printf(" bit_depth_luma_minus8 : %d \n", sps->bit_depth_luma_minus8 ); + printf(" bit_depth_chroma_minus8 : %d \n", sps->bit_depth_chroma_minus8 ); + printf(" qpprime_y_zero_transform_bypass_flag : %d \n", sps->qpprime_y_zero_transform_bypass_flag ); + printf(" seq_scaling_matrix_present_flag : %d \n", sps->seq_scaling_matrix_present_flag ); + // int seq_scaling_list_present_flag[8]; + // void* ScalingList4x4[6]; + // int UseDefaultScalingMatrix4x4Flag[6]; + // void* ScalingList8x8[2]; + // int UseDefaultScalingMatrix8x8Flag[2]; + printf(" log2_max_frame_num_minus4 : %d \n", sps->log2_max_frame_num_minus4 ); + printf(" pic_order_cnt_type : %d \n", sps->pic_order_cnt_type ); + printf(" log2_max_pic_order_cnt_lsb_minus4 : %d \n", sps->log2_max_pic_order_cnt_lsb_minus4 ); + printf(" delta_pic_order_always_zero_flag : %d \n", sps->delta_pic_order_always_zero_flag ); + printf(" offset_for_non_ref_pic : %d \n", sps->offset_for_non_ref_pic ); + printf(" offset_for_top_to_bottom_field : %d \n", sps->offset_for_top_to_bottom_field ); + printf(" num_ref_frames_in_pic_order_cnt_cycle : %d \n", sps->num_ref_frames_in_pic_order_cnt_cycle ); + // int offset_for_ref_frame[256]; + printf(" num_ref_frames : %d \n", sps->num_ref_frames ); + printf(" gaps_in_frame_num_value_allowed_flag : %d \n", sps->gaps_in_frame_num_value_allowed_flag ); + printf(" pic_width_in_mbs_minus1 : %d \n", sps->pic_width_in_mbs_minus1 ); + printf(" pic_height_in_map_units_minus1 : %d \n", sps->pic_height_in_map_units_minus1 ); + printf(" frame_mbs_only_flag : %d \n", sps->frame_mbs_only_flag ); + printf(" mb_adaptive_frame_field_flag : %d \n", sps->mb_adaptive_frame_field_flag ); + printf(" direct_8x8_inference_flag : %d \n", sps->direct_8x8_inference_flag ); + printf(" frame_cropping_flag : %d \n", sps->frame_cropping_flag ); + printf(" frame_crop_left_offset : %d \n", sps->frame_crop_left_offset ); + printf(" frame_crop_right_offset : %d \n", sps->frame_crop_right_offset ); + printf(" frame_crop_top_offset : %d \n", sps->frame_crop_top_offset ); + printf(" frame_crop_bottom_offset : %d \n", sps->frame_crop_bottom_offset ); + printf(" vui_parameters_present_flag : %d \n", sps->vui_parameters_present_flag ); + + printf("=== VUI ===\n"); + printf(" aspect_ratio_info_present_flag : %d \n", sps->vui.aspect_ratio_info_present_flag ); + printf(" aspect_ratio_idc : %d \n", sps->vui.aspect_ratio_idc ); + printf(" sar_width : %d \n", sps->vui.sar_width ); + printf(" sar_height : %d \n", sps->vui.sar_height ); + printf(" overscan_info_present_flag : %d \n", sps->vui.overscan_info_present_flag ); + printf(" overscan_appropriate_flag : %d \n", sps->vui.overscan_appropriate_flag ); + printf(" video_signal_type_present_flag : %d \n", sps->vui.video_signal_type_present_flag ); + printf(" video_format : %d \n", sps->vui.video_format ); + printf(" video_full_range_flag : %d \n", sps->vui.video_full_range_flag ); + printf(" colour_description_present_flag : %d \n", sps->vui.colour_description_present_flag ); + printf(" colour_primaries : %d \n", sps->vui.colour_primaries ); + printf(" transfer_characteristics : %d \n", sps->vui.transfer_characteristics ); + printf(" matrix_coefficients : %d \n", sps->vui.matrix_coefficients ); + printf(" chroma_loc_info_present_flag : %d \n", sps->vui.chroma_loc_info_present_flag ); + printf(" chroma_sample_loc_type_top_field : %d \n", sps->vui.chroma_sample_loc_type_top_field ); + printf(" chroma_sample_loc_type_bottom_field : %d \n", sps->vui.chroma_sample_loc_type_bottom_field ); + printf(" timing_info_present_flag : %d \n", sps->vui.timing_info_present_flag ); + printf(" num_units_in_tick : %d \n", sps->vui.num_units_in_tick ); + printf(" time_scale : %d \n", sps->vui.time_scale ); + printf(" fixed_frame_rate_flag : %d \n", sps->vui.fixed_frame_rate_flag ); + printf(" nal_hrd_parameters_present_flag : %d \n", sps->vui.nal_hrd_parameters_present_flag ); + printf(" vcl_hrd_parameters_present_flag : %d \n", sps->vui.vcl_hrd_parameters_present_flag ); + printf(" low_delay_hrd_flag : %d \n", sps->vui.low_delay_hrd_flag ); + printf(" pic_struct_present_flag : %d \n", sps->vui.pic_struct_present_flag ); + printf(" bitstream_restriction_flag : %d \n", sps->vui.bitstream_restriction_flag ); + printf(" motion_vectors_over_pic_boundaries_flag : %d \n", sps->vui.motion_vectors_over_pic_boundaries_flag ); + printf(" max_bytes_per_pic_denom : %d \n", sps->vui.max_bytes_per_pic_denom ); + printf(" max_bits_per_mb_denom : %d \n", sps->vui.max_bits_per_mb_denom ); + printf(" log2_max_mv_length_horizontal : %d \n", sps->vui.log2_max_mv_length_horizontal ); + printf(" log2_max_mv_length_vertical : %d \n", sps->vui.log2_max_mv_length_vertical ); + printf(" num_reorder_frames : %d \n", sps->vui.num_reorder_frames ); + printf(" max_dec_frame_buffering : %d \n", sps->vui.max_dec_frame_buffering ); + + printf("=== HRD ===\n"); + printf(" cpb_cnt_minus1 : %d \n", sps->hrd.cpb_cnt_minus1 ); + printf(" bit_rate_scale : %d \n", sps->hrd.bit_rate_scale ); + printf(" cpb_size_scale : %d \n", sps->hrd.cpb_size_scale ); + int SchedSelIdx; + for( SchedSelIdx = 0; SchedSelIdx <= sps->hrd.cpb_cnt_minus1; SchedSelIdx++ ) + { + printf(" bit_rate_value_minus1[%d] : %d \n", SchedSelIdx, sps->hrd.bit_rate_value_minus1[SchedSelIdx] ); // up to cpb_cnt_minus1, which is <= 31 + printf(" cpb_size_value_minus1[%d] : %d \n", SchedSelIdx, sps->hrd.cpb_size_value_minus1[SchedSelIdx] ); + printf(" cbr_flag[%d] : %d \n", SchedSelIdx, sps->hrd.cbr_flag[SchedSelIdx] ); + } + printf(" initial_cpb_removal_delay_length_minus1 : %d \n", sps->hrd.initial_cpb_removal_delay_length_minus1 ); + printf(" cpb_removal_delay_length_minus1 : %d \n", sps->hrd.cpb_removal_delay_length_minus1 ); + printf(" dpb_output_delay_length_minus1 : %d \n", sps->hrd.dpb_output_delay_length_minus1 ); + printf(" time_offset_length : %d \n", sps->hrd.time_offset_length ); +} + + + diff --git a/src/utils/h264_stream.h b/src/utils/h264_stream.h new file mode 100644 index 000000000..99e134e4a --- /dev/null +++ b/src/utils/h264_stream.h @@ -0,0 +1,165 @@ +/* + * h264bitstream - a library for reading and writing H.264 video + * Copyright (C) 2005-2007 Auroras Entertainment, LLC + * Copyright (C) 2008-2011 Avail-TVN + * + * Written by Alex Izvorski and Alex Giladi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _H264_STREAM_H +#define _H264_STREAM_H 1 + +#include +#include +#include + +#include "bs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Sequence Parameter Set + @see 7.3.2.1 Sequence parameter set RBSP syntax + @see read_seq_parameter_set_rbsp + @see write_seq_parameter_set_rbsp + @see debug_sps +*/ +typedef struct +{ + int profile_idc; + int constraint_set0_flag; + int constraint_set1_flag; + int constraint_set2_flag; + int constraint_set3_flag; + int constraint_set4_flag; + int constraint_set5_flag; + int reserved_zero_2bits; + int level_idc; + int seq_parameter_set_id; + int chroma_format_idc; + int residual_colour_transform_flag; + int bit_depth_luma_minus8; + int bit_depth_chroma_minus8; + int qpprime_y_zero_transform_bypass_flag; + int seq_scaling_matrix_present_flag; + int seq_scaling_list_present_flag[8]; + int* ScalingList4x4[6]; + int UseDefaultScalingMatrix4x4Flag[6]; + int* ScalingList8x8[2]; + int UseDefaultScalingMatrix8x8Flag[2]; + int log2_max_frame_num_minus4; + int pic_order_cnt_type; + int log2_max_pic_order_cnt_lsb_minus4; + int delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + int num_ref_frames_in_pic_order_cnt_cycle; + int offset_for_ref_frame[256]; + int num_ref_frames; + int gaps_in_frame_num_value_allowed_flag; + int pic_width_in_mbs_minus1; + int pic_height_in_map_units_minus1; + int frame_mbs_only_flag; + int mb_adaptive_frame_field_flag; + int direct_8x8_inference_flag; + int frame_cropping_flag; + int frame_crop_left_offset; + int frame_crop_right_offset; + int frame_crop_top_offset; + int frame_crop_bottom_offset; + int vui_parameters_present_flag; + + struct + { + int aspect_ratio_info_present_flag; + int aspect_ratio_idc; + int sar_width; + int sar_height; + int overscan_info_present_flag; + int overscan_appropriate_flag; + int video_signal_type_present_flag; + int video_format; + int video_full_range_flag; + int colour_description_present_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + int chroma_loc_info_present_flag; + int chroma_sample_loc_type_top_field; + int chroma_sample_loc_type_bottom_field; + int timing_info_present_flag; + int num_units_in_tick; + int time_scale; + int fixed_frame_rate_flag; + int nal_hrd_parameters_present_flag; + int vcl_hrd_parameters_present_flag; + int low_delay_hrd_flag; + int pic_struct_present_flag; + int bitstream_restriction_flag; + int motion_vectors_over_pic_boundaries_flag; + int max_bytes_per_pic_denom; + int max_bits_per_mb_denom; + int log2_max_mv_length_horizontal; + int log2_max_mv_length_vertical; + int num_reorder_frames; + int max_dec_frame_buffering; + } vui; + + struct + { + int cpb_cnt_minus1; + int bit_rate_scale; + int cpb_size_scale; + int bit_rate_value_minus1[32]; // up to cpb_cnt_minus1, which is <= 31 + int cpb_size_value_minus1[32]; + int cbr_flag[32]; + int initial_cpb_removal_delay_length_minus1; + int cpb_removal_delay_length_minus1; + int dpb_output_delay_length_minus1; + int time_offset_length; + } hrd; + +} sps_t; + +/** + H264 stream + Contains data structures for all NAL types that can be handled by this library. + When reading, data is read into those, and when writing it is written from those. + The reason why they are all contained in one place is that some of them depend on others, we need to + have all of them available to read or write correctly. + */ + +int nal_to_rbsp(const uint8_t* nal_buf, int* nal_size, uint8_t* rbsp_buf, int* rbsp_size); + +int read_seq_parameter_set_rbsp(sps_t* h, bs_t* b); +void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int useDefaultScalingMatrixFlag ); +void read_vui_parameters(sps_t* h, bs_t* b); +void read_hrd_parameters(sps_t* h, bs_t* b); + +void read_rbsp_trailing_bits(bs_t* b); + +void debug_sps(sps_t* sps); + +#define SAR_Extended 255 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 4882015e0..a73798a1f 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -77,44 +77,46 @@ //TODO set lower initial video recv buffer size (to find the minimal?) #define INITIAL_VIDEO_RECV_BUFFER_SIZE ((0.1*1920*1080)*110/100) //command line net.core setup: sysctl -w net.core.rmem_max=9123840 +#define DEFAULT_VIDEO_FRAME_WIDTH 1920 +#define DEFAULT_VIDEO_FRAME_HEIGHT 1080 /* error handling macros */ #define my_curl_easy_setopt(A, B, C) \ if ((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK){ \ fprintf(stderr, "[rtsp error] curl_easy_setopt(%s, %s, %s) failed: %d\n", #A, #B, #C, res); \ printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ - exit(0); \ + return NULL; \ } #define my_curl_easy_perform(A) \ if ((res = curl_easy_perform((A))) != CURLE_OK){ \ fprintf(stderr, "[rtsp error] curl_easy_perform(%s) failed: %d\n", #A, res); \ printf("[rtsp error] could not configure rtsp capture properly, \n\t\tplease check your parameters. \nExiting...\n\n"); \ - exit(0); \ + return NULL; \ } /* send RTSP GET_PARAMETERS request */ -static void +static int rtsp_get_parameters(CURL *curl, const char *uri); /* send RTSP OPTIONS request */ -static void +static int rtsp_options(CURL *curl, const char *uri); /* send RTSP DESCRIBE request and write sdp response to a file */ -static void +static int rtsp_describe(CURL *curl, const char *uri, const char *sdp_filename); /* send RTSP SETUP request */ -static void +static int rtsp_setup(CURL *curl, const char *uri, const char *transport); /* send RTSP PLAY request */ -static void +static int rtsp_play(CURL *curl, const char *uri, const char *range); /* send RTSP TEARDOWN request */ -static void +static int rtsp_teardown(CURL *curl, const char *uri); /* convert url into an sdp filename */ @@ -122,7 +124,7 @@ static void get_sdp_filename(const char *url, char *sdp_filename); static int -get_nals(const char *sdp_filename, char *nals); +get_nals(const char *sdp_filename, char *nals, int *width, int *height); static int init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals); @@ -136,17 +138,19 @@ vidcap_rtsp_thread(void *args); static void show_help(void); +void getNewLine(const char* buffer, int* i, char* line); + +void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state); + void rtsp_keepalive(void *state); -FILE *F_video_rtsp = NULL; +static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; + /** * @struct rtsp_state */ struct video_rtsp_state { - char *nals; - int nals_size; - char *data; //nals + data uint32_t *in_codec; char *codec; @@ -155,10 +159,8 @@ struct video_rtsp_state { int frames; struct video_frame *frame; struct tile *tile; - int width; - int height; - struct std_frame_received *rx_data; + //struct std_frame_received *rx_data; bool new_frame; bool decompress; bool grab; @@ -237,6 +239,13 @@ struct rtsp_state { volatile bool should_exit; struct audio_rtsp_state *artsp_state; struct video_rtsp_state *vrtsp_state; + + pthread_t keep_alive_rtsp_thread_id; //the worker_id + pthread_mutex_t lock; + pthread_cond_t worker_cv; + volatile bool worker_waiting; + pthread_cond_t boss_cv; + volatile bool boss_waiting; }; static void @@ -252,7 +261,7 @@ show_help() { } void -rtsp_keepalive(void *state) { +rtsp_keepalive_video(void *state) { struct rtsp_state *s; s = (struct rtsp_state *) state; struct timeval now; @@ -263,6 +272,15 @@ rtsp_keepalive(void *state) { } } +static void * +keep_alive_thread(void *arg){ + struct rtsp_state *s; + s = (struct rtsp_state *) arg; + while (!s->should_exit) { + rtsp_keepalive_video(s); + } +} + static void * vidcap_rtsp_thread(void *arg) { struct rtsp_state *s; @@ -275,11 +293,7 @@ vidcap_rtsp_thread(void *arg) { gettimeofday(&s->vrtsp_state->curr_time, NULL); s->vrtsp_state->timestamp = tv_diff(s->vrtsp_state->curr_time, s->vrtsp_state->start_time) * 90000; - rtsp_keepalive(s); - rtp_update(s->vrtsp_state->device, s->vrtsp_state->curr_time); - //TODO no need of rtcp communication between ug and rtsp server? - //rtp_send_ctrl(s->device, s->timestamp, 0, s->curr_time); s->vrtsp_state->timeout.tv_sec = 0; s->vrtsp_state->timeout.tv_usec = 10000; @@ -299,7 +313,7 @@ vidcap_rtsp_thread(void *arg) { s->vrtsp_state->worker_waiting = false; } if (pbuf_decode(s->vrtsp_state->cp->playout_buffer, s->vrtsp_state->curr_time, - decode_frame_h264, s->vrtsp_state->rx_data)) + decode_frame_h264, s->vrtsp_state->frame)) { s->vrtsp_state->new_frame = true; } @@ -337,22 +351,31 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { } gettimeofday(&s->vrtsp_state->curr_time, NULL); - s->vrtsp_state->frame->h264_iframe = s->vrtsp_state->rx_data->iframe; - s->vrtsp_state->frame->h264_iframe = s->vrtsp_state->rx_data->iframe; - s->vrtsp_state->frame->tiles[0].data_len = s->vrtsp_state->rx_data->buffer_len; - memcpy(s->vrtsp_state->data + s->vrtsp_state->nals_size, s->vrtsp_state->rx_data->frame_buffer, - s->vrtsp_state->rx_data->buffer_len); - memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->data, - s->vrtsp_state->rx_data->buffer_len + s->vrtsp_state->nals_size); - s->vrtsp_state->frame->tiles[0].data_len += s->vrtsp_state->nals_size; + + s->vrtsp_state->frame->tiles[0].data_len = s->vrtsp_state->frame->h264_buffer_len; + s->vrtsp_state->frame->tiles[0].data = s->vrtsp_state->frame->h264_buffer; + + if(s->vrtsp_state->frame->h264_offset_len>0 && s->vrtsp_state->frame->h264_frame_type == INTRA){ + memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len); + } if (s->vrtsp_state->decompress) { + if(s->vrtsp_state->des.width != s->vrtsp_state->frame->h264_width || s->vrtsp_state->des.height != s->vrtsp_state->frame->h264_height){ + s->vrtsp_state->des.width = s->vrtsp_state->frame->h264_width; + s->vrtsp_state->des.height = s->vrtsp_state->frame->h264_height; + decompress_done(s->vrtsp_state->sd); + s->vrtsp_state->frame->color_spec = H264; + if (init_decompressor(s->vrtsp_state) == 0) + return NULL; + s->vrtsp_state->frame->color_spec = UYVY; + } + decompress_frame(s->vrtsp_state->sd, (unsigned char *) s->vrtsp_state->out_frame, (unsigned char *) s->vrtsp_state->frame->tiles[0].data, - s->vrtsp_state->rx_data->buffer_len + s->vrtsp_state->nals_size, 0); + s->vrtsp_state->frame->h264_buffer_len, 0); s->vrtsp_state->frame->tiles[0].data = s->vrtsp_state->out_frame; //TODO memcpy? s->vrtsp_state->frame->tiles[0].data_len = vc_get_linesize(s->vrtsp_state->des.width, UYVY) - * s->vrtsp_state->des.height; //TODO reconfigurable? + * s->vrtsp_state->des.height; //TODO reconfigurable? } s->vrtsp_state->new_frame = false; @@ -408,8 +431,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { gettimeofday(&s->vrtsp_state->t0, NULL); s->vrtsp_state->frames = 0; - s->vrtsp_state->nals = malloc(1024); - s->vrtsp_state->grab = false; + s->vrtsp_state->grab = FALSE; s->addr = "127.0.0.1"; s->vrtsp_state->device = NULL; @@ -426,11 +448,14 @@ vidcap_rtsp_init(const struct vidcap_params *params) { (s->vrtsp_state->required_connections) * sizeof(struct rtp *)); s->vrtsp_state->participants = pdb_init(); - s->vrtsp_state->rx_data = malloc(sizeof(struct std_frame_received)); - s->vrtsp_state->new_frame = false; + s->vrtsp_state->new_frame = FALSE; s->vrtsp_state->in_codec = malloc(sizeof(uint32_t *) * 10); + s->vrtsp_state->frame = vf_alloc(1); + s->vrtsp_state->frame->h264_offset_buffer = malloc(2048); + s->vrtsp_state->frame->h264_offset_len = 0; + s->uri = NULL; s->curl = NULL; char *fmt = NULL; @@ -466,39 +491,17 @@ vidcap_rtsp_init(const struct vidcap_params *params) { } break; case 1: - if (tmp) { //TODO check if it's a number + if (tmp) { //TODO check if it's a number s->vrtsp_state->port = atoi(tmp); - } else { - printf("\n[rtsp] Wrong format for port! \n"); - show_help(); - exit(0); - } - break; - case 2: - if (tmp) { //TODO check if it's a number - s->vrtsp_state->width = atoi(tmp); - } else { - printf("\n[rtsp] Wrong format for width! \n"); - show_help(); - exit(0); - } - break; - case 3: - if (tmp) { //TODO check if it's a number - s->vrtsp_state->height = atoi(tmp); //Now checking if we have user and password parameters... - if (s->vrtsp_state->height == 0) { - int ntmp = 0; - ntmp = s->vrtsp_state->width; - s->vrtsp_state->width = s->vrtsp_state->port; - s->vrtsp_state->height = ntmp; + if (s->vrtsp_state->port == 0) { sprintf(s->uri, "rtsp:%s", uri_tmp1); s->vrtsp_state->port = atoi(uri_tmp2); if (tmp) { if (strcmp(tmp, "true") == 0) - s->vrtsp_state->decompress = true; + s->vrtsp_state->decompress = TRUE; else if (strcmp(tmp, "false") == 0) - s->vrtsp_state->decompress = false; + s->vrtsp_state->decompress = FALSE; else { printf("\n[rtsp] Wrong format for boolean decompress flag! \n"); show_help(); @@ -513,12 +516,12 @@ vidcap_rtsp_init(const struct vidcap_params *params) { exit(0); } break; - case 4: + case 2: if (tmp) { if (strcmp(tmp, "true") == 0) - s->vrtsp_state->decompress = true; + s->vrtsp_state->decompress = TRUE; else if (strcmp(tmp, "false") == 0) - s->vrtsp_state->decompress = false; + s->vrtsp_state->decompress = FALSE; else { printf( "\n[rtsp] Wrong format for boolean decompress flag! \n"); @@ -528,7 +531,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { } else continue; break; - case 5: + case 3: continue; } fmt = NULL; @@ -536,20 +539,17 @@ vidcap_rtsp_init(const struct vidcap_params *params) { } } //re-check parameters - if (s->vrtsp_state->height == 0) { - int ntmp = 0; - ntmp = s->vrtsp_state->width; - s->vrtsp_state->width = (int) s->vrtsp_state->port; - s->vrtsp_state->height = (int) ntmp; + if (s->vrtsp_state->port == 0) { sprintf(s->uri, "rtsp:%s", uri_tmp1); s->vrtsp_state->port = (int) atoi(uri_tmp2); } + s->vrtsp_state->frame->h264_width = DEFAULT_VIDEO_FRAME_WIDTH/2; + s->vrtsp_state->frame->h264_height = DEFAULT_VIDEO_FRAME_HEIGHT/2; + debug_msg("[rtsp] selected flags:\n"); debug_msg("\t uri: %s\n",s->uri); debug_msg("\t port: %d\n", s->vrtsp_state->port); - debug_msg("\t width: %d\n",s->vrtsp_state->width); - debug_msg("\t height: %d\n",s->vrtsp_state->height); debug_msg("\t decompress: %d\n\n",s->vrtsp_state->decompress); if (uri_tmp1 != NULL) @@ -557,24 +557,33 @@ vidcap_rtsp_init(const struct vidcap_params *params) { if (uri_tmp2 != NULL) free(uri_tmp2); - s->vrtsp_state->rx_data->frame_buffer = malloc(4 * s->vrtsp_state->width * s->vrtsp_state->height); - s->vrtsp_state->data = malloc(4 * s->vrtsp_state->width * s->vrtsp_state->height + s->vrtsp_state->nals_size); + s->vrtsp_state->frame->h264_offset_len = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->frame->h264_offset_buffer); + + if(s->vrtsp_state->frame->h264_offset_len<0){ + return NULL; + //TODO CLEAN UP MALLOCS... + } + + s->vrtsp_state->frame->h264_buffer = malloc(4 * s->vrtsp_state->frame->h264_width * s->vrtsp_state->frame->h264_height); + + s->vrtsp_state->frame->h264_buffer_len = 0; + s->vrtsp_state->frame->h264_media_time = 0; + s->vrtsp_state->frame->h264_seqno = 0; - s->vrtsp_state->frame = vf_alloc(1); s->vrtsp_state->frame->isStd = TRUE; - s->vrtsp_state->frame->h264_bframe = FALSE; - s->vrtsp_state->frame->h264_iframe = FALSE; + s->vrtsp_state->frame->h264_frame_type = BFRAME; + s->vrtsp_state->tile = vf_get_tile(s->vrtsp_state->frame, 0); - vf_get_tile(s->vrtsp_state->frame, 0)->width = s->vrtsp_state->width; - vf_get_tile(s->vrtsp_state->frame, 0)->height = s->vrtsp_state->height; + vf_get_tile(s->vrtsp_state->frame, 0)->width = s->vrtsp_state->frame->h264_width; + vf_get_tile(s->vrtsp_state->frame, 0)->height = s->vrtsp_state->frame->h264_height; //TODO fps should be autodetected, now reset and controlled at vidcap_grab function s->vrtsp_state->frame->fps = 30; s->vrtsp_state->fps = 30; s->vrtsp_state->frame->interlacing = PROGRESSIVE; - s->vrtsp_state->frame->tiles[0].data = calloc(1, s->vrtsp_state->width * s->vrtsp_state->height); + s->vrtsp_state->frame->tiles[0].data = calloc(1, s->vrtsp_state->frame->h264_width * s->vrtsp_state->frame->h264_height); - s->should_exit = false; + s->should_exit = FALSE; s->vrtsp_state->device = rtp_init_if(NULL, s->vrtsp_state->mcast_if, s->vrtsp_state->port, 0, s->vrtsp_state->ttl, s->vrtsp_state->rtcp_bw, 0, rtp_recv_callback, (void *) s->vrtsp_state->participants, 0); @@ -612,22 +621,15 @@ vidcap_rtsp_init(const struct vidcap_params *params) { s->vrtsp_state->boss_waiting = false; s->vrtsp_state->worker_waiting = false; - s->vrtsp_state->nals_size = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->nals); - - if (s->vrtsp_state->nals_size >= 0) - memcpy(s->vrtsp_state->data, s->vrtsp_state->nals, s->vrtsp_state->nals_size); - else{ - printf("\n[rtsp] something went wrong with the sdp parser...\n"); - return NULL; - } - if (s->vrtsp_state->decompress) { + s->vrtsp_state->frame->color_spec = H264; if (init_decompressor(s->vrtsp_state) == 0) return NULL; s->vrtsp_state->frame->color_spec = UYVY; } pthread_create(&s->vrtsp_state->vrtsp_thread_id, NULL, vidcap_rtsp_thread, s); + pthread_create(&s->keep_alive_rtsp_thread_id, NULL, keep_alive_thread, s); debug_msg("[rtsp] rtsp capture init done\n"); @@ -692,30 +694,44 @@ init_rtsp(char* rtsp_uri, int rtsp_port, void *state, char* nals) { //http://curl.haxx.se/libcurl/c/curl_easy_perform.html /* request server options */ - rtsp_options(curl, uri); - printf("sdp_file: %s\n", sdp_filename); + if(rtsp_options(curl, uri)==0){ + return -1; + } + /* request session description and write response to sdp file */ - rtsp_describe(curl, uri, sdp_filename); + if(rtsp_describe(curl, uri, sdp_filename)==0){ + return -1; + } setup_codecs_and_controls_from_sdp(sdp_filename, s); if (s->vrtsp_state->codec == "H264"){ s->vrtsp_state->frame->color_spec = H264; sprintf(uri, "%s/%s", url, s->vrtsp_state->control); debug_msg("\n V URI = %s\n",uri); - rtsp_setup(curl, uri, Vtransport); + if(rtsp_setup(curl, uri, Vtransport)==0){ + return -1; + } sprintf(uri, "%s", url); } if (s->artsp_state->codec == "PCMU"){ sprintf(uri, "%s/%s", url, s->artsp_state->control); debug_msg("\n A URI = %s\n",uri); - rtsp_setup(curl, uri, Atransport); + if(rtsp_setup(curl, uri, Atransport)==0){ + return -1; + } sprintf(uri, "%s", url); } - if (s->artsp_state->codec == "" && s->vrtsp_state->codec == "") return -1; - else rtsp_play(curl, uri, range); + if (s->artsp_state->codec == "" && s->vrtsp_state->codec == ""){ + return -1; + } + else{ + if(rtsp_play(curl, uri, range)==0){ + return -1; + } + } /* get start nal size attribute from sdp file */ - len_nals = get_nals(sdp_filename, nals); + len_nals = get_nals(sdp_filename, nals, &s->vrtsp_state->frame->h264_width, &s->vrtsp_state->frame->h264_height); s->curl = curl; s->uri = uri; @@ -770,7 +786,7 @@ void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { buffer[fileSize] = '\0'; while (buffer[n] != '\0'){ - newLine(buffer,&n,line); + getNewLine(buffer,&n,line); sscanf(line, " a = control: %s", tmpBuff); tmpBuff = strstr(line, "track"); if(tmpBuff!=NULL){ @@ -806,8 +822,8 @@ void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { for(int p=0;p<2;p++){ if(strncmp(codecs[p],"H264",4)==0){ - rtspState->vrtsp_state->codec = "H264"; - rtspState->vrtsp_state->control = tracks[p]; + rtspState->vrtsp_state->codec = "H264"; + rtspState->vrtsp_state->control = tracks[p]; }if(strncmp(codecs[p],"PCMU",4)==0){ rtspState->artsp_state->codec = "PCMU"; @@ -819,7 +835,7 @@ void setup_codecs_and_controls_from_sdp(const char *sdp_filename, void *state) { fclose(fp); } -void newLine(const char* buffer, int* i, char* line){ +void getNewLine(const char* buffer, int* i, char* line){ int j=0; while(buffer[*i] != '\n' && buffer[*i] != '\0'){ j++; @@ -850,8 +866,8 @@ init_decompressor(void *state) { if (decompress_is_available(LIBAVCODEC_MAGIC)) { sr->sd = decompress_init(LIBAVCODEC_MAGIC); - sr->des.width = sr->width; - sr->des.height = sr->height; + sr->des.width = sr->frame->h264_width; + sr->des.height = sr->frame->h264_height; sr->des.color_spec = sr->frame->color_spec; sr->des.tile_count = 0; sr->des.interlacing = PROGRESSIVE; @@ -860,24 +876,32 @@ init_decompressor(void *state) { vc_get_linesize(sr->des.width, UYVY), UYVY); } else return 0; - sr->out_frame = malloc(sr->width * sr->height * 4); + sr->out_frame = malloc(sr->frame->h264_width * sr->frame->h264_height * 4); return 1; } -static void +/** + * send RTSP GET PARAMS request + */ +static int rtsp_get_parameters(CURL *curl, const char *uri) { CURLcode res = CURLE_OK; - debug_msg("\n[rtsp] GET_PARAMETERS %s\n", uri); my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri); my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_GET_PARAMETER); - my_curl_easy_perform(curl); + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP GET PARAMETERS] curl_easy_perform failed\n"); + error_msg("[RTSP GET PARAMETERS] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + }else{ + return 1; + } } /** * send RTSP OPTIONS request */ -static void +static int rtsp_options(CURL *curl, const char *uri) { char control[1500], *user, *pass, *strtoken; user = malloc(1500); @@ -905,13 +929,20 @@ rtsp_options(CURL *curl, const char *uri) { my_curl_easy_setopt(curl, CURLOPT_PASSWORD, pass); my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_OPTIONS); - my_curl_easy_perform(curl); + + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP OPTIONS] curl_easy_perform failed\n"); + error_msg("[RTSP OPTIONS] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + }else{ + return 1; + } } /** * send RTSP DESCRIBE request and write sdp response to a file */ -static void +static int rtsp_describe(CURL *curl, const char *uri, const char *sdp_filename) { CURLcode res = CURLE_OK; FILE *sdp_fp = fopen(sdp_filename, "wt"); @@ -925,17 +956,24 @@ rtsp_describe(CURL *curl, const char *uri, const char *sdp_filename) { my_curl_easy_setopt(curl, CURLOPT_WRITEDATA, sdp_fp); my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_DESCRIBE); - my_curl_easy_perform(curl); + + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP DESCRIBE] curl_easy_perform failed\n"); + error_msg("[RTSP DESCRIBE] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + } + my_curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout); if (sdp_fp != stdout) { fclose(sdp_fp); } + return 1; } /** * send RTSP SETUP request */ -static void +static int rtsp_setup(CURL *curl, const char *uri, const char *transport) { CURLcode res = CURLE_OK; debug_msg("\n[rtsp] SETUP %s\n", uri); @@ -943,34 +981,54 @@ rtsp_setup(CURL *curl, const char *uri, const char *transport) { my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri); my_curl_easy_setopt(curl, CURLOPT_RTSP_TRANSPORT, transport); my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_SETUP); - my_curl_easy_perform(curl); + + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP SETUP] curl_easy_perform failed\n"); + error_msg("[RTSP SETUP] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + }else{ + return 1; + } } /** * send RTSP PLAY request */ -static void +static int rtsp_play(CURL *curl, const char *uri, const char *range) { CURLcode res = CURLE_OK; debug_msg("\n[rtsp] PLAY %s\n", uri); my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri); //my_curl_easy_setopt(curl, CURLOPT_RANGE, range); //range not set because we want (right now) no limit range for streaming duration my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_PLAY); - my_curl_easy_perform(curl); + + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP PLAY] curl_easy_perform failed\n"); + error_msg("[RTSP PLAY] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + }else{ + return 1; + } } /** * send RTSP TEARDOWN request */ -static void +static int rtsp_teardown(CURL *curl, const char *uri) { CURLcode res = CURLE_OK; debug_msg("\n[rtsp] TEARDOWN %s\n", uri); my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long )CURL_RTSPREQ_TEARDOWN); - my_curl_easy_perform(curl); -} + if (curl_easy_perform(curl) != CURLE_OK){ + error_msg("[RTSP TEARD DOWN] curl_easy_perform failed\n"); + error_msg("[RTSP TEARD DOWN] could not configure rtsp capture properly, \n\t\tplease check your parameters. \ncleaning...\n\n"); + return 0; + }else{ + return 1; + } +} /** * convert url into an sdp filename */ @@ -1006,27 +1064,39 @@ vidcap_rtsp_done(void *state) { s->should_exit = true; pthread_join(s->vrtsp_state->vrtsp_thread_id, NULL); + pthread_join(s->keep_alive_rtsp_thread_id, NULL); + + if(s->vrtsp_state->decompress) + decompress_done(s->vrtsp_state->sd); + + rtp_done(s->vrtsp_state->device); + + if(s->vrtsp_state->frame->h264_buffer!=NULL) free(s->vrtsp_state->frame->h264_buffer); + if(s->vrtsp_state->frame->h264_offset_buffer!=NULL) free(s->vrtsp_state->frame->h264_offset_buffer); + if(s->vrtsp_state->frame!=NULL) free(s->vrtsp_state->frame); + if(s->vrtsp_state!=NULL) free(s->vrtsp_state); + if(s->artsp_state!=NULL) free(s->artsp_state); - free(s->vrtsp_state->rx_data->frame_buffer); - free(s->vrtsp_state->data); rtsp_teardown(s->curl, s->uri); curl_easy_cleanup(s->curl); s->curl = NULL; - if (s->vrtsp_state->decompress) - decompress_done(s->vrtsp_state->sd); - rtp_done(s->vrtsp_state->device); - free(s); } /** - * scan sdp file for media control attribute to generate nal starting bytes + * scan sdp file for media control attributes to generate coded frame required params (WxH and offset) */ static int -get_nals(const char *sdp_filename, char *nals) { +get_nals(const char *sdp_filename, char *nals, int *width, int *height) { + + uint8_t nalInfo; + uint8_t type; + uint8_t nri; + int k; + int sizeSPS = 0; int max_len = 1500, len_nals = 0; char *s = malloc(max_len); char *sprop; @@ -1040,11 +1110,8 @@ get_nals(const char *sdp_filename, char *nals) { gsize length; //gsize is an unsigned int. char *nal_aux, *nals_aux, *nal; nals_aux = malloc(max_len); - nals[0] = 0x00; - nals[1] = 0x00; - nals[2] = 0x00; - nals[3] = 0x01; - len_nals = 4; + memcpy(nals, start_sequence, sizeof(start_sequence)); + len_nals = sizeof(start_sequence); nal_aux = strstr(sprop, "="); nal_aux++; nal = strtok(nal_aux, ",;"); @@ -1053,23 +1120,39 @@ get_nals(const char *sdp_filename, char *nals) { memcpy(nals + len_nals, nals_aux, length); len_nals += length; + nalInfo = (uint8_t) nals[4]; + type = nalInfo & 0x1f; + nri = nalInfo & 0x60; + + if (type == 7){ + width_height_from_SDP(width, height , (nals+4), length); + } + while ((nal = strtok(NULL, ",;")) != NULL) { nals_aux = g_base64_decode(nal, &length); if (length) { //convert base64 to hex - nals[len_nals] = 0x00; - nals[len_nals + 1] = 0x00; - nals[len_nals + 2] = 0x00; - nals[len_nals + 3] = 0x01; - len_nals += 4; + memcpy(nals+len_nals, start_sequence, sizeof(start_sequence)); + len_nals += sizeof(start_sequence); memcpy(nals + len_nals, nals_aux, length); len_nals += length; - } //end if (length) { - } //end while ((nal = strtok(NULL, ",;")) != NULL){ - } //end if (sprop != NULL) { - } //end while (fgets(s, max_len - 2, sdp_fp) != NULL) { + + nalInfo = (uint8_t) nals[len_nals - length]; + type = nalInfo & 0x1f; + nri = nalInfo & 0x60; + + if (type == 7){ + width_height_from_SDP(width, height , (nals+(len_nals - length)), length); + } + //assure start sequence injection between sps, pps and other nals + memcpy(nals+len_nals, start_sequence, sizeof(start_sequence)); + len_nals += sizeof(start_sequence); + } + } + } + } fclose(sdp_fp); - } //end if (sdp_fp != NULL) { + } free(s); return len_nals; From b10ba5313a795c7f22f5aaa1b7787c4863d95b6c Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Wed, 19 Feb 2014 21:18:40 +0100 Subject: [PATCH 18/57] parsing tricky nals when intra received... --- src/rtp/rtp.h | 2 +- src/transmit.c | 1 + src/video_capture/rtsp.c | 25 +++++++++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/rtp/rtp.h b/src/rtp/rtp.h index fd94f6499..7fb6a2297 100644 --- a/src/rtp/rtp.h +++ b/src/rtp/rtp.h @@ -251,7 +251,7 @@ int rtp_send_data_hdr(struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, uint32_t csrc[], char *phdr, int phdr_len, - char *data, int data_len, + char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type); void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, struct timeval curr_time); diff --git a/src/transmit.c b/src/transmit.c index a5607df37..4006a69b3 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -956,6 +956,7 @@ static void tx_send_base_h264(struct tx *tx, struct tile *tile, struct rtp *rtp_ int fragmentation = 0; int nal_max_size = tx->mtu - 40; + if (nal.size > nal_max_size) { debug_msg("RTP packet size exceeds the MTU size\n"); fragmentation = 1; diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index a73798a1f..46a50d5a8 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -315,7 +315,7 @@ vidcap_rtsp_thread(void *arg) { if (pbuf_decode(s->vrtsp_state->cp->playout_buffer, s->vrtsp_state->curr_time, decode_frame_h264, s->vrtsp_state->frame)) { - s->vrtsp_state->new_frame = true; + s->vrtsp_state->new_frame = true; } if (s->vrtsp_state->boss_waiting) pthread_cond_signal(&s->vrtsp_state->boss_cv); @@ -338,6 +338,12 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { struct rtsp_state *s; s = (struct rtsp_state *) state; + + //TODO FREEEEEEE + char * tmp = malloc(1920*1080*6); + + + *audio = NULL; if(pthread_mutex_trylock(&s->vrtsp_state->lock)==0){ @@ -356,7 +362,20 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { s->vrtsp_state->frame->tiles[0].data = s->vrtsp_state->frame->h264_buffer; if(s->vrtsp_state->frame->h264_offset_len>0 && s->vrtsp_state->frame->h264_frame_type == INTRA){ - memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len); + if(s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len] == 0 && + s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+1] == 0 && + s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+2] == 0 && + s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+3] == 1 ){ + + memcpy(tmp, s->vrtsp_state->frame->tiles[0].data+4,s->vrtsp_state->frame->tiles[0].data_len-4); + memcpy(tmp, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len-4); + s->vrtsp_state->frame->tiles[0].data_len-=4; + memcpy(s->vrtsp_state->frame->tiles[0].data, tmp, s->vrtsp_state->frame->tiles[0].data_len); + + } + else{ + memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len); + } } if (s->vrtsp_state->decompress) { @@ -383,6 +402,8 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { pthread_cond_signal(&s->vrtsp_state->worker_cv); } } + + pthread_mutex_unlock(&s->vrtsp_state->lock); gettimeofday(&s->vrtsp_state->t, NULL); From fcd6fe457b0ac87425c3163e3ffea573527bd515 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 28 Feb 2014 14:12:05 +0100 Subject: [PATCH 19/57] add decode frame switching by PT --- src/video_capture/rtsp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index bfa877705..2da5b6027 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -77,9 +77,9 @@ #define VERSION_STR "V1.0" //TODO set lower initial video recv buffer size (to find the minimal?) -#define INITIAL_VIDEO_RECV_BUFFER_SIZE ((0.1*1920*1080)*110/100) //command line net.core setup: sysctl -w net.core.rmem_max=9123840 #define DEFAULT_VIDEO_FRAME_WIDTH 1920 #define DEFAULT_VIDEO_FRAME_HEIGHT 1080 +#define INITIAL_VIDEO_RECV_BUFFER_SIZE ((0.1*DEFAULT_VIDEO_FRAME_WIDTH*DEFAULT_VIDEO_FRAME_HEIGHT)*110/100) //command line net.core setup: sysctl -w net.core.rmem_max=9123840 /* error handling macros */ #define my_curl_easy_setopt(A, B, C) \ @@ -285,6 +285,7 @@ keep_alive_thread(void *arg){ rtsp_keepalive_video(s); } } + int decode_frame_by_pt(struct coded_data *cdata, void *decode_data) { rtp_packet *pckt = NULL; pckt = cdata->data; @@ -292,8 +293,6 @@ int decode_frame_by_pt(struct coded_data *cdata, void *decode_data) { switch(pckt->pt){ case PT_H264: return decode_frame_h264(cdata,decode_data); - case PT_VIDEO: - return decode_video_frame(cdata,decode_data); default: error_msg("Wrong Payload type: %u\n", pckt->pt); return FALSE; From cb5c04d75c2e72d27942881243093e6e97e2d166 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 28 Feb 2014 16:58:05 +0100 Subject: [PATCH 20/57] going back and rtsp improvements --- src/video_capture/rtsp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 2da5b6027..23afcbdd9 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -272,7 +272,11 @@ rtsp_keepalive_video(void *state) { struct timeval now; gettimeofday(&now, NULL); if (tv_diff(now, s->vrtsp_state->prev_time) >= 20) { - rtsp_get_parameters(s->curl, s->uri); + if(rtsp_get_parameters(s->curl, s->uri)==0){ + s->should_exit = TRUE; + vidcap_rtsp_done(s); + exit(0); + } gettimeofday(&s->vrtsp_state->prev_time, NULL); } } @@ -465,6 +469,7 @@ vidcap_rtsp_init(const struct vidcap_params *params) { s->artsp_state->control = ""; s->artsp_state->control = ""; + int len = -1; char *save_ptr = NULL; s->avType = none; //-1 none, 0 a&v, 1 v, 2 a @@ -596,11 +601,12 @@ vidcap_rtsp_init(const struct vidcap_params *params) { if (uri_tmp2 != NULL) free(uri_tmp2); - s->vrtsp_state->frame->h264_offset_len = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->frame->h264_offset_buffer); + len = init_rtsp(s->uri, s->vrtsp_state->port, s, s->vrtsp_state->frame->h264_offset_buffer); - if(s->vrtsp_state->frame->h264_offset_len<0){ + if(len < 0){ return NULL; - //TODO CLEAN UP MALLOCS... + }else{ + s->vrtsp_state->frame->h264_offset_len = len; } s->vrtsp_state->frame->h264_buffer = malloc(4 * s->vrtsp_state->frame->h264_width * s->vrtsp_state->frame->h264_height); @@ -1101,7 +1107,7 @@ void vidcap_rtsp_done(void *state) { struct rtsp_state *s = state; - s->should_exit = true; + s->should_exit = TRUE; pthread_join(s->vrtsp_state->vrtsp_thread_id, NULL); pthread_join(s->keep_alive_rtsp_thread_id, NULL); From 8f47dae29123b5bd13e9e862c94019f85bc74f40 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 15:09:18 +0100 Subject: [PATCH 21/57] rtsp already working with huge refactor from CESNET, now reparing audio messaging api issue --- src/rtsp/BasicRTSPOnlyServer.cpp | 3 ++- src/rtsp/BasicRTSPOnlySubsession.cpp | 2 -- src/sender.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rtsp/BasicRTSPOnlyServer.cpp b/src/rtsp/BasicRTSPOnlyServer.cpp index 399e9f56a..14bff4acb 100644 --- a/src/rtsp/BasicRTSPOnlyServer.cpp +++ b/src/rtsp/BasicRTSPOnlyServer.cpp @@ -81,8 +81,9 @@ int BasicRTSPOnlyServer::init_server() { if (env != NULL || rtspServer != NULL || mod == NULL || (avType >= NUM_RTSP_FORMATS && avType < 0)){ exit(1); } + //setting livenessTimeoutTask - unsigned reclamationTestSeconds = 25; + unsigned reclamationTestSeconds = 5; TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); diff --git a/src/rtsp/BasicRTSPOnlySubsession.cpp b/src/rtsp/BasicRTSPOnlySubsession.cpp index a25c231e0..8c8f3010b 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.cpp +++ b/src/rtsp/BasicRTSPOnlySubsession.cpp @@ -240,8 +240,6 @@ void BasicRTSPOnlySubsession::startStream(unsigned clientSessionId, if(avType == audioPCMUdyn || avType == avStdDyn){ char pathA[1024]; - struct msg_sender *msg = (struct msg_sender *) - new_message(sizeof(struct msg_sender)); memset(pathA, 0, sizeof(pathA)); enum module_class path_sender[] = { MODULE_CLASS_AUDIO, MODULE_CLASS_SENDER, MODULE_CLASS_NONE }; append_message_path(pathA, sizeof(pathA), path_sender); diff --git a/src/sender.c b/src/sender.c index 6ea77a5eb..67ca5ac07 100644 --- a/src/sender.c +++ b/src/sender.c @@ -253,7 +253,7 @@ static void h264_rtp_send(void *state, struct video_frame *tx_frame) } } - VIDEO_FRAME_DISPOSE(tx_frame); + //VIDEO_FRAME_DISPOSE(tx_frame); } static void h264_rtp_done(void *state) From 87de2c4b1c52027f5debb376b8870975d38a6309 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 17:01:14 +0100 Subject: [PATCH 22/57] import done from huge refactor --- src/main.cpp | 9 +++------ src/messaging.cpp | 2 +- src/video_rxtx/h264_rtp.cpp | 2 +- src/video_rxtx/h264_rtp.h | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 095033456..ef5e1e5c4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -424,6 +424,7 @@ int main(int argc, char *argv[]) const char *requested_audio_fec = DEFAULT_AUDIO_FEC; char *audio_channel_map = NULL; const char *audio_scale = "mixauto"; + rtsp_serv_t* rtsp_server = NULL; bool isStd = FALSE; int recv_port_number = PORT_BASE; int send_port_number = PORT_BASE; @@ -948,17 +949,13 @@ int main(int argc, char *argv[]) display_device, requested_mtu, argc, argv); }else if (video_protocol == H264_STD) { -#ifdef HAVE_RTSP_SERVER rtps_types_t avType; if(strcmp("none", vidcap_params_get_driver(vidcap_params_head)) != 0 && (strcmp("none",audio_send) != 0)) avType = avStdDyn; //AVStream else if((strcmp("none",audio_send) != 0)) avType = audioPCMUdyn; //AStream else if(strcmp("none", vidcap_params_get_driver(vidcap_params_head))) avType = videoH264; //VStream - else printf("[RTSP SERVER] no stream type... check capture devices input\n"); - rtsp_server = init_rtsp_server(0, &root_mod, avType); //port, root_module, avType - c_start_server(rtsp_server); -#endif + else printf("[RTSP SERVER CHECK] no stream type... check capture devices input...\n"); - uv->state_video_rxtx = new h264_rtp_video_rxtx(&root_mod, video_exporter, + uv->state_video_rxtx = new h264_rtp_video_rxtx(&root_mod, video_exporter, requested_compression, requested_encryption, requested_receiver, recv_port_number, send_port_number, ipv6, requested_mcast_if, requested_video_fec, requested_mtu, diff --git a/src/messaging.cpp b/src/messaging.cpp index a35a0630a..f7a715dd0 100644 --- a/src/messaging.cpp +++ b/src/messaging.cpp @@ -27,7 +27,7 @@ struct response *send_message(struct module *root, const char *const_path, struc while ((item = strtok_r(path, ".", &save_ptr))) { struct module *old_receiver = receiver; - receiver = get_matching_child(receiver, path); + receiver = get_matching_child(receiver, item); if (!receiver) { printf("Receiver %s not yet exists. Message will be delivered " diff --git a/src/video_rxtx/h264_rtp.cpp b/src/video_rxtx/h264_rtp.cpp index b262ce9ac..928902fc6 100644 --- a/src/video_rxtx/h264_rtp.cpp +++ b/src/video_rxtx/h264_rtp.cpp @@ -55,7 +55,7 @@ h264_rtp_video_rxtx::h264_rtp_video_rxtx(struct module *parent, struct video_exp const char *requested_compression, const char *requested_encryption, const char *receiver, int rx_port, int tx_port, bool use_ipv6, const char *mcast_if, const char *requested_video_fec, int mtu, - long packet_rate, uint8_t avType) : + long packet_rate, rtps_types_t avType) : rtp_video_rxtx(parent, video_exporter, requested_compression, requested_encryption, receiver, rx_port, tx_port, use_ipv6, mcast_if, requested_video_fec, mtu, packet_rate) diff --git a/src/video_rxtx/h264_rtp.h b/src/video_rxtx/h264_rtp.h index b487aa35d..5f9cee75c 100644 --- a/src/video_rxtx/h264_rtp.h +++ b/src/video_rxtx/h264_rtp.h @@ -52,7 +52,7 @@ public: const char *requested_compression, const char *requested_encryption, const char *receiver, int rx_port, int tx_port, bool use_ipv6, const char *mcast_if, const char *requested_video_fec, int mtu, - long packet_rate, uint8_t avType); + long packet_rate, rtps_types_t avType); virtual ~h264_rtp_video_rxtx(); private: virtual void send_frame(struct video_frame *); From 00f4ff1b2c9ab1d81aea5ee7bd57b10561337b05 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 17:14:22 +0100 Subject: [PATCH 23/57] merge --- Makefile.in | 1 - src/capture_filter.c | 2 - src/video_capture.c | 11 -- src/video_capture/muxer.c | 380 -------------------------------------- src/video_capture/muxer.h | 68 ------- 5 files changed, 462 deletions(-) delete mode 100644 src/video_capture/muxer.c delete mode 100644 src/video_capture/muxer.h diff --git a/Makefile.in b/Makefile.in index b7bb05790..d7bd33173 100644 --- a/Makefile.in +++ b/Makefile.in @@ -123,7 +123,6 @@ OBJS = @OBJS@ \ src/video_codec.o \ src/video_capture.o \ src/video_capture/aggregate.o \ - src/video_capture/muxer.o \ src/video_capture/import.o \ src/video_capture/null.o \ src/video_compress.o \ diff --git a/src/capture_filter.c b/src/capture_filter.c index 40700ee85..ab1092c82 100644 --- a/src/capture_filter.c +++ b/src/capture_filter.c @@ -61,7 +61,6 @@ #include "capture_filter/every.h" #include "capture_filter/logo.h" #include "capture_filter/none.h" -#include "video_capture/muxer.h" static struct capture_filter_info *capture_filters[] = { @@ -69,7 +68,6 @@ static struct capture_filter_info *capture_filters[] = { &capture_filter_every, &capture_filter_logo, &capture_filter_none, - &capture_filter_muxer, }; struct capture_filter { diff --git a/src/video_capture.c b/src/video_capture.c index c43679f70..a24ac1355 100644 --- a/src/video_capture.c +++ b/src/video_capture.c @@ -81,7 +81,6 @@ #include "video_capture/testcard2.h" #include "video_capture/v4l2.h" #include "video_capture/rtsp.h" -#include "video_capture/muxer.h" #define VIDCAP_MAGIC 0x76ae98f0 @@ -299,16 +298,6 @@ struct vidcap_device_api vidcap_device_table[] = { MK_NAME(vidcap_testcard_grab), NULL }, - { - /* Mixer of many vid cap devices */ - 0, - "muxer", - MK_NAME(vidcap_muxer_probe), - MK_NAME(vidcap_muxer_init), - MK_NAME(vidcap_muxer_done), - MK_NAME(vidcap_muxer_grab), - NULL - }, #if defined HAVE_TESTCARD2 || defined BUILD_LIBRARIES { /* Dummy sender for testing purposes */ diff --git a/src/video_capture/muxer.c b/src/video_capture/muxer.c deleted file mode 100644 index 686473270..000000000 --- a/src/video_capture/muxer.c +++ /dev/null @@ -1,380 +0,0 @@ -/** - * @file video_capture/muxer.c - * @author Gerard Castillo - * - * @brief Muxer of video capturers, N to 1. - */ -/* - * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of Fundació i2CAT nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "host.h" -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" - -#include "debug.h" -#include "video.h" -#include "video_capture.h" - -#include "capture_filter.h" -#include "messaging.h" -#include "module.h" - -#include "tv.h" - -#include "video_capture/muxer.h" -#include "audio/audio.h" - -#include -#include -#include -#include -#include -#include - -struct vidcap_muxer_state { - struct module mod; - - struct vidcap **devices; - int devices_cnt; - - struct video_frame *frame; - struct video_frame *prev_frame; - int frames; - struct timeval t, t0; - - int dev_index_curr; - int dev_index_next; - - int audio_source_index; - int change; -}; -static struct vidcap_muxer_state *muxer_state; - -/** - * MUXER REMOTE CONTROL - */ -static int init(struct module *parent, const char *cfg, void **state); -static void done(void *state); -static struct video_frame *filter(void *state, struct video_frame *in); - -static int init(struct module *parent, const char *cfg, void **state) -{ - int ch = atoi(cfg); - if(ch > 0 && ch < muxer_state->devices_cnt) muxer_state->change = atoi(cfg); - //else printf("\n[MUXER REMOTE CONTROL] ERROR: devices available from 1 to %d\n",muxer_state->devices_cnt-1); - - *state = muxer_state; - return 0; -} -static void done(void *state) -{ - struct vidcap_muxer_state *s = state; - module_done(&s->mod); - if(state!=NULL)free(state); -} -static struct video_frame *filter(void *state, struct video_frame *in) -{ - return in; -} -struct capture_filter_info capture_filter_muxer = { - .name = "muxer", - .init = init, - .done = done, - .filter = filter, -}; -/** - * MUXER CAPTURE - */ -/* prototypes of functions defined in this module */ -static void show_help(void); - -static void show_help() -{ - printf("Muxer capture\n"); - printf("Usage\n"); - printf("\t-t muxer -t -t ....]\n"); - printf("\t\twhere devn_config is a complete configuration string of device involved in the muxer device\n"); -} - - -struct vidcap_type * -vidcap_muxer_probe(void) -{ - struct vidcap_type* vt; - - vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type)); - if (vt != NULL) { - vt->id = VIDCAP_MUXER_ID; - vt->name = "muxer"; - vt->description = "Muxer video capture"; - } - return vt; -} - -void * -vidcap_muxer_init(const struct vidcap_params *params) -{ - //struct vidcap_muxer_state *s; - int i; - - printf("vidcap_muxer_init\n"); - - muxer_state = (struct vidcap_muxer_state *) calloc(1, - sizeof(struct vidcap_muxer_state)); - if (muxer_state == NULL) { - printf("Unable to allocate muxer capture state\n"); - return NULL; - } - - muxer_state->audio_source_index = -1; - muxer_state->frames = 0; - muxer_state->dev_index_curr = 1; - muxer_state->dev_index_next = 1; - muxer_state->change = 0; - - gettimeofday(&muxer_state->t0, NULL); - - if (vidcap_params_get_fmt(params) - && strcmp(vidcap_params_get_fmt(params), "") != 0) - { - show_help(); - return &vidcap_init_noerr; - } - - muxer_state->devices_cnt = 1; - const struct vidcap_params *tmp = params; - while ((tmp = vidcap_params_get_next(tmp))) { - if (vidcap_params_get_driver(tmp) != NULL) - muxer_state->devices_cnt++; - else - break; - } - - muxer_state->devices = calloc(muxer_state->devices_cnt, sizeof(struct vidcap *)); - i = 0; - tmp = params; - for (int i = 1; i < muxer_state->devices_cnt; ++i) { - tmp = vidcap_params_get_next(tmp); - - int ret = initialize_video_capture(NULL, tmp, &muxer_state->devices[i]); - if (ret != 0) { - fprintf(stderr, "[muxer] Unable to initialize device %d (%s:%s).\n", - i, vidcap_params_get_driver(tmp), vidcap_params_get_fmt(tmp)); - goto error; - } - } - - muxer_state->frame = vf_alloc(1); - - return muxer_state; - - error: if (muxer_state->devices) { - int i; - for (i = 1u; i < muxer_state->devices_cnt; ++i) { - if (muxer_state->devices[i]) { - vidcap_done(muxer_state->devices[i]); - } - } - } - free(muxer_state); - return NULL; -} - -void -vidcap_muxer_done(void *state) -{ - struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; - - assert(s != NULL); - - if (s != NULL) { - int i; - for (i = 1; i < s->devices_cnt; ++i) { - vidcap_done(s->devices[i]); - } - } - - vf_free(s->frame); -} - -struct video_frame * -vidcap_muxer_grab(void *state, struct audio_frame **audio) -{ - struct vidcap_muxer_state *s = (struct vidcap_muxer_state *) state; - struct audio_frame *audio_frame = NULL; - struct video_frame *frame_curr = NULL; - struct video_frame *frame_next = NULL; - struct video_frame *frame = NULL; - - /** - * remote control (now keyboard handler) - */ - set_conio_terminal_mode(); - int c; - if (kbhit()) { - c = (int) getch(); - debug_msg("num %d pressed...\r\n", c); - } - if(c >= 48 && c < 48+s->devices_cnt){ - // s->dev_index_curr = s->dev_index_next; - s->dev_index_next = c - 48; - //printf("\n[MUXER] device %d (previous was: %d) selected of %d devices...\r\n",s->dev_index_next,s->dev_index_curr,s->devices_cnt-1); - } - reset_terminal_mode(); - -// /** -// * REMOTE CONTROL -// */ -// struct message *msg; -// while ((msg = check_message(&s->mod))) { -// process_message(s,((struct msg_universal *) msg)->text); -// free_message(msg); -// } - if(s->change != 0){ - s->dev_index_next = s->change; - s->change = 0; - } - /** - * vidcap_grap - */ - while (!frame_curr) { - frame_curr = vidcap_grab(s->devices[s->dev_index_curr], &audio_frame); - } - if(s->dev_index_next != s->dev_index_curr){ - while (!frame_next) { - frame_next = vidcap_grab(s->devices[s->dev_index_next], &audio_frame); - } - - //printf("\n\n[MUXER] frameNext is std = %d...\n\n",frame_next->isStd); - - if(frame_next->isStd == TRUE){ - //printf("\n\n[MUXER] RTSP INCOMING FRAME...\n"); - if(frame_next->h264_frame_type == INTRA){ - s->dev_index_curr = s->dev_index_next; - frame_curr = frame_next; - //printf("[MUXER] GOT INTRA FRAME! SWITCHING...\n\n"); - }//else printf("[MUXER] NO INTRA FRAME YET...\n"); - }else{ - frame_curr = frame_next; - s->dev_index_curr = s->dev_index_next; - } - } - frame = frame_curr; - - if (audio_frame) { - *audio = audio_frame; - } else { - *audio = NULL; - } - if (s->audio_source_index == -1 && audio_frame != NULL) { - fprintf(stderr, "[muxer] Locking device #%d as an audio source.\n", - s->dev_index_curr); - s->audio_source_index = s->dev_index_curr; - } - if (s->audio_source_index == s->dev_index_curr) { - *audio = audio_frame; - } - if (frame != NULL) { - vf_get_tile(s->frame, 0)->width = vf_get_tile(frame, 0)->width; - vf_get_tile(s->frame, 0)->height = vf_get_tile(frame, 0)->height; - vf_get_tile(s->frame, 0)->data_len = vf_get_tile(frame, 0)->data_len; - vf_get_tile(s->frame, 0)->data = vf_get_tile(frame, 0)->data; - s->frame->color_spec = frame->color_spec; - s->frame->interlacing = frame->interlacing; - if (frame->fps == 0) - s->frame->fps = 15; - else - s->frame->fps = frame->fps; - } else - return NULL; - - s->frames++; - gettimeofday(&s->t, NULL); - double seconds = tv_diff(s->t, s->t0); - if (seconds >= 5) { - float fps = s->frames / seconds; - fprintf(stderr, "[muxer] %d frames in %g seconds = %g FPS\n", s->frames, - seconds, fps); - s->t0 = s->t; - s->frames = 0; - } - - return s->frame; -} - -/** - * KEYBOARD HANDLER - */ - -struct termios orig_termios; - -void reset_terminal_mode() -{ - tcsetattr(0, TCSANOW, &orig_termios); -} - -void set_conio_terminal_mode() -{ - struct termios new_termios; - - /* take two copies - one for now, one for later */ - tcgetattr(0, &orig_termios); - memcpy(&new_termios, &orig_termios, sizeof(new_termios)); - - /* register cleanup handler, and set the new terminal mode */ - atexit(reset_terminal_mode); - cfmakeraw(&new_termios); - tcsetattr(0, TCSANOW, &new_termios); -} - -int kbhit() -{ - struct timeval tv = { 0L, 0L }; - fd_set fds; - FD_ZERO(&fds); - FD_SET(0, &fds); - return select(1, &fds, NULL, NULL, &tv); -} - -int getch() -{ - int r; - unsigned char c; - if ((r = read(0, &c, sizeof(c))) < 0) { - return r; - } else { - return c; - } -} - diff --git a/src/video_capture/muxer.h b/src/video_capture/muxer.h deleted file mode 100644 index 550d3b523..000000000 --- a/src/video_capture/muxer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * FILE: muxer.h - * AUTHORS: Gerard Castillo - * - * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * - * This product includes software developed by Fundació i2CAT, - * Internet I Innovació Digital a Catalunya - * - * 4. Neither the name of the CESNET nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef _MUXER_H_ -#define _MUXER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define VIDCAP_MUXER_ID 0x9bd6abc0 //md5 hash of VIDCAP_MUXER_ID string == 241c3648599dc72ce3f119a99bd6abc0 - -struct vidcap_type * -vidcap_muxer_probe(void); -void * -vidcap_muxer_init(const struct vidcap_params *params); -void -vidcap_muxer_done(void *state); -struct video_frame * -vidcap_muxer_grab(void *state, struct audio_frame **audio); - - -struct capture_filter_info; -extern struct capture_filter_info capture_filter_muxer; - -#endif - -#ifdef __cplusplus -} // END extern "C" -#endif From 206fe69f832da08779c8f2530ef0ea84da9fa756 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 18:06:24 +0100 Subject: [PATCH 24/57] huge import done --- src/rtp/rtpdec_h264.c | 2 -- src/rtsp/BasicRTSPOnlyServer.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index cca8f868f..708b5f417 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -59,9 +59,7 @@ static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len); int decode_frame_h264(struct coded_data *cdata, void *decode_data) { - rtp_packet *pckt = NULL; - int substream = 0; struct coded_data *orig = cdata; uint8_t nal; diff --git a/src/rtsp/BasicRTSPOnlyServer.cpp b/src/rtsp/BasicRTSPOnlyServer.cpp index 14bff4acb..6712324e5 100644 --- a/src/rtsp/BasicRTSPOnlyServer.cpp +++ b/src/rtsp/BasicRTSPOnlyServer.cpp @@ -83,7 +83,7 @@ int BasicRTSPOnlyServer::init_server() { } //setting livenessTimeoutTask - unsigned reclamationTestSeconds = 5; + unsigned reclamationTestSeconds = 25; TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); From 5b8a007bddb8db135ce13252b06ffc3ce9c2662d Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 18:07:26 +0100 Subject: [PATCH 25/57] unused variable --- src/rtp/rtpdec_h264.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rtp/rtpdec_h264.c b/src/rtp/rtpdec_h264.c index cca8f868f..708b5f417 100644 --- a/src/rtp/rtpdec_h264.c +++ b/src/rtp/rtpdec_h264.c @@ -59,9 +59,7 @@ static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len); int decode_frame_h264(struct coded_data *cdata, void *decode_data) { - rtp_packet *pckt = NULL; - int substream = 0; struct coded_data *orig = cdata; uint8_t nal; From 06ecebb2b45e9563781aeed420c9c485f5a90731 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 18:12:18 +0100 Subject: [PATCH 26/57] rtsp server reclamationTestSeconds to 25 --- src/rtsp/BasicRTSPOnlyServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtsp/BasicRTSPOnlyServer.cpp b/src/rtsp/BasicRTSPOnlyServer.cpp index 14bff4acb..6712324e5 100644 --- a/src/rtsp/BasicRTSPOnlyServer.cpp +++ b/src/rtsp/BasicRTSPOnlyServer.cpp @@ -83,7 +83,7 @@ int BasicRTSPOnlyServer::init_server() { } //setting livenessTimeoutTask - unsigned reclamationTestSeconds = 5; + unsigned reclamationTestSeconds = 25; TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); From 1ac8e344cb1f5f2fbc717fe1568c517099c7fdd0 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 18:22:10 +0100 Subject: [PATCH 27/57] clean up with closing rtsp server statement --- src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index ef5e1e5c4..247d7ebb0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1048,6 +1048,10 @@ cleanup: vidcap_params_head = next; } +#ifdef HAVE_RTSP_SERVER + if(rtsp_server) c_stop_server(rtsp_server); +#endif + module_done(&root_mod); free(uv); From 31fdfca3276d226b81422243f2870eafd0a01a9f Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 10 Mar 2014 18:22:59 +0100 Subject: [PATCH 28/57] clean up with closing rtsp server statement --- src/main.cpp | 64 ++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ef5e1e5c4..9453f542a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -93,14 +93,14 @@ #include #endif -#define EXIT_FAIL_USAGE 1 -#define EXIT_FAIL_UI 2 -#define EXIT_FAIL_DISPLAY 3 -#define EXIT_FAIL_CAPTURE 4 -#define EXIT_FAIL_NETWORK 5 -#define EXIT_FAIL_TRANSMIT 6 -#define EXIT_FAIL_COMPRESS 7 -#define EXIT_FAIL_DECODER 8 +#define EXIT_FAIL_USAGE 1 +#define EXIT_FAIL_UI 2 +#define EXIT_FAIL_DISPLAY 3 +#define EXIT_FAIL_CAPTURE 4 +#define EXIT_FAIL_NETWORK 5 +#define EXIT_FAIL_TRANSMIT 6 +#define EXIT_FAIL_COMPRESS 7 +#define EXIT_FAIL_DECODER 8 #define PORT_BASE 5004 #define PORT_AUDIO 5006 @@ -452,8 +452,8 @@ int main(int argc, char *argv[]) pthread_t receiver_thread_id, capture_thread_id; - bool receiver_thread_started = false, - capture_thread_started = false; + bool receiver_thread_started = false, + capture_thread_started = false; unsigned display_flags = 0; int compressed_audio_sample_rate = 48000; int ret; @@ -543,11 +543,11 @@ int main(int argc, char *argv[]) return 0; } requested_display = optarg; - if(strchr(optarg, ':')) { - char *delim = strchr(optarg, ':'); - *delim = '\0'; - display_cfg = delim + 1; - } + if(strchr(optarg, ':')) { + char *delim = strchr(optarg, ':'); + *delim = '\0'; + display_cfg = delim + 1; + } break; case 't': if (!strcmp(optarg, "help")) { @@ -625,9 +625,9 @@ int main(int argc, char *argv[]) requested_video_fec = optarg; } break; - case 'h': - usage(); - return 0; + case 'h': + usage(); + return 0; case 'P': if(strchr(optarg, ':')) { char *save_ptr = NULL; @@ -814,17 +814,17 @@ int main(int argc, char *argv[]) } #ifdef WIN32 - WSADATA wsaData; - int err = WSAStartup(MAKEWORD(2, 2), &wsaData); - if(err != 0) { - fprintf(stderr, "WSAStartup failed with error %d.", err); - return EXIT_FAILURE; - } - if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { - fprintf(stderr, "Counld not found usable version of Winsock.\n"); - WSACleanup(); - return EXIT_FAILURE; - } + WSADATA wsaData; + int err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if(err != 0) { + fprintf(stderr, "WSAStartup failed with error %d.", err); + return EXIT_FAILURE; + } + if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + fprintf(stderr, "Counld not found usable version of Winsock.\n"); + WSACleanup(); + return EXIT_FAILURE; + } #endif if(control_init(control_port, &control, &root_mod) != 0) { @@ -1048,6 +1048,10 @@ cleanup: vidcap_params_head = next; } +#ifdef HAVE_RTSP_SERVER + if(rtsp_server) c_stop_server(rtsp_server); +#endif + module_done(&root_mod); free(uv); @@ -1056,7 +1060,7 @@ cleanup: #endif #ifdef WIN32 - WSACleanup(); + WSACleanup(); #endif printf("Exit\n"); From c4d82c9343e2e2880b4921c6430739b7480048eb Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 12:20:18 +0100 Subject: [PATCH 29/57] resize capture filter ready to implement frame resize by external API --- Makefile.in | 1 + src/capture_filter.c | 2 + src/capture_filter/resize.c | 166 ++++++++++++++++++++++++++++++++++++ src/capture_filter/resize.h | 57 +++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 src/capture_filter/resize.c create mode 100644 src/capture_filter/resize.h diff --git a/Makefile.in b/Makefile.in index b7bb05790..4b45c6cf8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -83,6 +83,7 @@ OBJS = @OBJS@ \ @SPEEX_OBJ@ \ src/capture_filter.o \ src/capture_filter/blank.o \ + src/capture_filter/resize.o \ src/capture_filter/every.o \ src/capture_filter/logo.o \ src/capture_filter/none.o \ diff --git a/src/capture_filter.c b/src/capture_filter.c index 40700ee85..9f4e9a14c 100644 --- a/src/capture_filter.c +++ b/src/capture_filter.c @@ -61,11 +61,13 @@ #include "capture_filter/every.h" #include "capture_filter/logo.h" #include "capture_filter/none.h" +#include "capture_filter/resize.h" #include "video_capture/muxer.h" static struct capture_filter_info *capture_filters[] = { &capture_filter_blank, + &capture_filter_resize, &capture_filter_every, &capture_filter_logo, &capture_filter_none, diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c new file mode 100644 index 000000000..be9f7b10c --- /dev/null +++ b/src/capture_filter/resize.c @@ -0,0 +1,166 @@ +/* + * FILE: capture_filter/resize.c + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif /* HAVE_CONFIG_H */ + +#include "capture_filter.h" + +#include "debug.h" + +#include "video.h" +#include "video_codec.h" + +#define MAX_TILES 1 + +struct module; + +static int init(struct module *parent, const char *cfg, void **state); +static void done(void *state); +static struct video_frame *filter(void *state, struct video_frame *in); +int resize(char *data, unsigned int data_len, int numerator, int denominator); + +struct state_resize { + int num; + int denom; + struct video_frame *frame; +}; + +static void usage() { + printf("\nUp/Downscaling by scale factor:\n\n"); + printf("resize usage:\n"); + printf("\tresize:numerator[/denominator]\n\n"); + printf("Downscaling example: resize:2 - downscale input frame size by scale factor of 2\n"); + printf("Upscaling example: resize:1/2 - upscale input frame size by scale factor of 2\n"); +} + +static int init(struct module *parent, const char *cfg, void **state) +{ + UNUSED(parent); + + int n; + int denom = 1;; + if(cfg) { + if(strcasecmp(cfg, "help") == 0) { + usage(); + return 1; + } + n = atoi(cfg); + if(strchr(cfg, '/')) { + denom = atoi(strchr(cfg, '/') + 1); + } + } else { + usage(); + return -1; + } + + if(n <= 0 || denom <= 0){ + printf("\n[RESIZE ERROR] numerator and denominator resize factors must be greater than zero!\n"); + usage(); + return -1; + } + + struct state_resize *s = calloc(1, sizeof(struct state_resize)); + s->num = n; + s->denom = denom; + s->frame = vf_alloc(MAX_TILES); + + *state = s; + return 0; +} + +static void done(void *state) +{ + struct state_resize *s = state; + + vf_free(s->frame); + free(state); +} + +int resize(char *data, unsigned int data_len, int numerator, int denominator){ + int res = 0; + + //TODO RESIZE METHOD HERE!!! + + return res; +} + +static struct video_frame *filter(void *state, struct video_frame *in) +{ + struct state_resize *s = state; + int i; + int res = 0; + assert(in->tile_count <= MAX_TILES); + memcpy(s->frame, in, sizeof(struct video_frame)); + memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); + + for(i=0; iframe->tile_count;i++){ + + res = resize(s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->num, s->denom); + + if(res!=0){ + printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); + printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); + return in; + } + + s->frame->tiles[i].width *= s->num; + s->frame->tiles[i].width /= s->denom; + s->frame->tiles[i].height *= s->num; + s->frame->tiles[i].height /= s->denom; + } + + return s->frame; +} + +struct capture_filter_info capture_filter_resize = { + .name = "resize", + .init = init, + .done = done, + .filter = filter, +}; + diff --git a/src/capture_filter/resize.h b/src/capture_filter/resize.h new file mode 100644 index 000000000..bd4eb9213 --- /dev/null +++ b/src/capture_filter/resize.h @@ -0,0 +1,57 @@ +/* + * FILE: capture_filter/resize.h + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CAPTURE_FILTER_RESIZE_H_ +#define CAPTURE_FILTER_RESIZE_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_win32.h" +#include "config_unix.h" +#endif // HAVE_CONFIG_H + +struct capture_filter_info; +extern struct capture_filter_info capture_filter_resize; + +#endif // CAPTURE_FILTER_RESIZE_H_ From 7af2ba5d99349817d803fef5a55176bfd5fd666e Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 14:36:33 +0100 Subject: [PATCH 30/57] resize struct additions --- src/capture_filter/resize.c | 41 ++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c index be9f7b10c..94a732419 100644 --- a/src/capture_filter/resize.c +++ b/src/capture_filter/resize.c @@ -55,19 +55,29 @@ #include "video.h" #include "video_codec.h" -#define MAX_TILES 1 +#define MAX_TILES 16 struct module; static int init(struct module *parent, const char *cfg, void **state); static void done(void *state); static struct video_frame *filter(void *state, struct video_frame *in); -int resize(char *data, unsigned int data_len, int numerator, int denominator); +//int resize(char *data, unsigned int data_len, struct opencv_tile_struct *opencv); +//int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv, unsigned int width, unsigned int height, int num, int denom); + +struct opencv_tile_struct { + int width; + int height; + + +}; struct state_resize { int num; int denom; + int reinit; struct video_frame *frame; + struct opencv_tile_struct **opencv; }; static void usage() { @@ -105,9 +115,11 @@ static int init(struct module *parent, const char *cfg, void **state) } struct state_resize *s = calloc(1, sizeof(struct state_resize)); + s->reinit = 0; s->num = n; s->denom = denom; s->frame = vf_alloc(MAX_TILES); + s->opencv = calloc(MAX_TILES, sizeof(struct opencv_tile_struct*)); *state = s; return 0; @@ -121,7 +133,7 @@ static void done(void *state) free(state); } -int resize(char *data, unsigned int data_len, int numerator, int denominator){ +int resize(char *data, unsigned int data_len, struct opencv_tile_struct *opencv){ int res = 0; //TODO RESIZE METHOD HERE!!! @@ -129,18 +141,36 @@ int resize(char *data, unsigned int data_len, int numerator, int denominator){ return res; } +int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, int num, int denom){ + int res = 0; + + //TODO DALE VUEY + + return 0; +} + static struct video_frame *filter(void *state, struct video_frame *in) { struct state_resize *s = state; - int i; + int i, j; int res = 0; assert(in->tile_count <= MAX_TILES); memcpy(s->frame, in, sizeof(struct video_frame)); memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); + if(s->reinit == 0){ + for(i=0; iframe->tile_count;i++){ + res = reconfigure_opencv_tile_struct(s->opencv[i], s->frame->tiles[i].width, s->frame->tiles[i].height, s->num, s->denom); + if(res!=0){ + //TODO ERROR!!! + } + } + s->reinit = 1; + } + for(i=0; iframe->tile_count;i++){ - res = resize(s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->num, s->denom); + res = resize(s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->opencv[i]); if(res!=0){ printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); @@ -154,6 +184,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) s->frame->tiles[i].height /= s->denom; } + return s->frame; } From bbaf59340ed02d476381e173b8da2f71891f9b5c Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 15:32:11 +0100 Subject: [PATCH 31/57] input and output buffers for resize --- src/capture_filter/resize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c index 94a732419..4b48307a5 100644 --- a/src/capture_filter/resize.c +++ b/src/capture_filter/resize.c @@ -133,7 +133,7 @@ static void done(void *state) free(state); } -int resize(char *data, unsigned int data_len, struct opencv_tile_struct *opencv){ +int resize(char *indata, char *outdata, unsigned int data_len, struct opencv_tile_struct *opencv){ int res = 0; //TODO RESIZE METHOD HERE!!! @@ -170,7 +170,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ - res = resize(s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->opencv[i]); + res = resize(in->tiles[i].data, s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->opencv[i]); if(res!=0){ printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); From fba8a2b69ee4ce0ded99e14bd842aacfefe94bd5 Mon Sep 17 00:00:00 2001 From: Palau Date: Thu, 13 Mar 2014 15:56:11 +0100 Subject: [PATCH 32/57] Resize filter (OpenCV module) implemented --- src/capture_filter/resize.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c index 4b48307a5..ddb0fefc9 100644 --- a/src/capture_filter/resize.c +++ b/src/capture_filter/resize.c @@ -55,6 +55,9 @@ #include "video.h" #include "video_codec.h" +#include +#include + #define MAX_TILES 16 struct module; @@ -68,8 +71,8 @@ static struct video_frame *filter(void *state, struct video_frame *in); struct opencv_tile_struct { int width; int height; - - + float scale_factor; + Mat in, out; }; struct state_resize { @@ -133,18 +136,34 @@ static void done(void *state) free(state); } -int resize(char *indata, char *outdata, unsigned int data_len, struct opencv_tile_struct *opencv){ +int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv){ int res = 0; - //TODO RESIZE METHOD HERE!!! + if (indata == NULL || outdata == NULL || data_lent == NULL || opencv == NULL) { + return 1; + } + + opencv->in.data = indata; + opencv->out.data = outdata; + + cvtColor(opencv->in, opencv->out, CV_YUV2RGB_UYVY); + resize(out, out, Size(0,0), opencv->scale_factor, opencv->scale_factor, INTER_LINEAR); + + *data_len = out.step * out.rows * sizeof(char); return res; } -int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, int num, int denom){ +int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact){ int res = 0; - //TODO DALE VUEY + if (opencv == NULL || width == 0 || height == 0 || scale_factor == 0) { + return 1; + } + + opencv->in = Mat.create(height, width, CV_8UC2); + opencv->width = width; + opencv->height = height; return 0; } From 3ea2b7f65aa02535bf19ba2a7116526a574a5e27 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 17:03:38 +0100 Subject: [PATCH 33/57] add configure and haves for resize dependencies --- Makefile.in | 3 +-- configure.ac | 50 +++++++++++++++++++++++++++++++++++++ src/capture_filter.c | 4 +++ src/capture_filter/resize.c | 47 ++++------------------------------ 4 files changed, 60 insertions(+), 44 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4b45c6cf8..6af68236d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,7 +8,7 @@ LINKER = @LINKER@ COMMON_FLAGS = -g @DEFS@ -DPATH_PREFIX=@prefix@ -DLIB_DIR=@libdir@ -Wall -Wextra -Wpointer-arith -msse2 CFLAGS = @CFLAGS@ @X_CFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE CPPFLAGS = @CPPFLAGS@ -D_GNU_SOURCE -CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE +CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE NVCCFLAGS = @NVCCFLAGS@ LDFLAGS = @LDFLAGS@ LIBS += @LIBS@ @JACK_TRANS_LIB@ @MATHLIBS@ @COREAUDIO_LIB@ \ @@ -83,7 +83,6 @@ OBJS = @OBJS@ \ @SPEEX_OBJ@ \ src/capture_filter.o \ src/capture_filter/blank.o \ - src/capture_filter/resize.o \ src/capture_filter/every.o \ src/capture_filter/logo.o \ src/capture_filter/none.o \ diff --git a/configure.ac b/configure.ac index 2c94c3df6..78abefbd6 100644 --- a/configure.ac +++ b/configure.ac @@ -1297,6 +1297,55 @@ AC_SUBST(RTSP_SERVER_INC) AC_SUBST(RTSP_SERVER_LIB) AC_SUBST(RTSP_SERVER_OBJ) +# ------------------------------------------------------------------------------------------------- +# OpenCV stuff +# ------------------------------------------------------------------------------------------------- +OPENCV_INC= +OPENCV_LIB= +OPENCV_OBJ= +opencv=no + +AC_ARG_ENABLE(opencv, + AS_HELP_STRING([--disable-opencv], [disable OpenCV support (default is auto) - resize capture filter dependency]), + [opencv_req=$enableval], + [opencv_req=auto] + ) + +case $host in + *-linux-*) + PKG_CHECK_MODULES([OPENCV], [opencv], FOUND_OPENCV_H=yes, FOUND_OPENCV_H=no) + + if test $opencv_req != no -a $FOUND_OPENCV_H = yes + then + AC_DEFINE([HAVE_OPENCV], [1], [OpenCV support - resize capture filter dependency]) + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS ${OPENCV_CFLAGS}" + SAVED_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS ${OPENCV_CFLAGS}" + OPENCV_INC= + OPENCV_LIB="${OPENCV_LIBS}" + OPENCV_OBJ="src/capture_filter/resize.o src/capture_filter/resize_utils.o" + AC_SUBST(OPENCV_LIB_TARGET, "lib/ultragrid/vidcapfilter_opencv.so.$video_capture_abi_version") + LIB_TARGETS="$LIB_TARGETS $OPENCV_LIB_TARGET" + LIB_OBJS="$LIB_OBJS $OPENCV_OBJ" + opencv=yes + fi + ;; +esac + +if test $opencv_req = yes -a $opencv = no; then + AC_MSG_ERROR([OpenCV not found, may install OpenCV...?]); +fi + +LIB_MODULES="$LIB_MODULES $OPENCV_LIB" + +AC_SUBST(OPENCV_INC) +AC_SUBST(OPENCV_LIB) +AC_SUBST(OPENCV_OBJ) + + + +# ------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------- @@ -2634,6 +2683,7 @@ RESULT=\ DELTACAST ................... $deltacast DVS ......................... $dvs OpenGL ...................... $gl + OpenCV ...................... $opencv Quicktime ................... $quicktime SAGE ........................ $sage SDL ......................... $sdl diff --git a/src/capture_filter.c b/src/capture_filter.c index 9f4e9a14c..646edf24b 100644 --- a/src/capture_filter.c +++ b/src/capture_filter.c @@ -61,13 +61,17 @@ #include "capture_filter/every.h" #include "capture_filter/logo.h" #include "capture_filter/none.h" +#ifdef HAVE_OPENCV #include "capture_filter/resize.h" +#endif #include "video_capture/muxer.h" static struct capture_filter_info *capture_filters[] = { &capture_filter_blank, +#ifdef HAVE_OPENCV &capture_filter_resize, +#endif &capture_filter_every, &capture_filter_logo, &capture_filter_none, diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c index ddb0fefc9..45abd160d 100644 --- a/src/capture_filter/resize.c +++ b/src/capture_filter/resize.c @@ -55,8 +55,7 @@ #include "video.h" #include "video_codec.h" -#include -#include +#include "capture_filter/resize_utils.h" #define MAX_TILES 16 @@ -65,15 +64,6 @@ struct module; static int init(struct module *parent, const char *cfg, void **state); static void done(void *state); static struct video_frame *filter(void *state, struct video_frame *in); -//int resize(char *data, unsigned int data_len, struct opencv_tile_struct *opencv); -//int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv, unsigned int width, unsigned int height, int num, int denom); - -struct opencv_tile_struct { - int width; - int height; - float scale_factor; - Mat in, out; -}; struct state_resize { int num; @@ -136,37 +126,7 @@ static void done(void *state) free(state); } -int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv){ - int res = 0; - if (indata == NULL || outdata == NULL || data_lent == NULL || opencv == NULL) { - return 1; - } - - opencv->in.data = indata; - opencv->out.data = outdata; - - cvtColor(opencv->in, opencv->out, CV_YUV2RGB_UYVY); - resize(out, out, Size(0,0), opencv->scale_factor, opencv->scale_factor, INTER_LINEAR); - - *data_len = out.step * out.rows * sizeof(char); - - return res; -} - -int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact){ - int res = 0; - - if (opencv == NULL || width == 0 || height == 0 || scale_factor == 0) { - return 1; - } - - opencv->in = Mat.create(height, width, CV_8UC2); - opencv->width = width; - opencv->height = height; - - return 0; -} static struct video_frame *filter(void *state, struct video_frame *in) { @@ -181,7 +141,10 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ res = reconfigure_opencv_tile_struct(s->opencv[i], s->frame->tiles[i].width, s->frame->tiles[i].height, s->num, s->denom); if(res!=0){ - //TODO ERROR!!! + printf("\n[RESIZE ERROR] error reconfiguring structs...\n"); + printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); + s->reinit = 1; + return in; } } s->reinit = 1; From 1f1812707286a2cb6cb6b5dbbd96e583154989dc Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 17:05:54 +0100 Subject: [PATCH 34/57] add cpp utils for resize --- src/capture_filter/resize_utils.cpp | 33 +++++++++++++++++++++++++++++ src/capture_filter/resize_utils.h | 31 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/capture_filter/resize_utils.cpp create mode 100644 src/capture_filter/resize_utils.h diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp new file mode 100644 index 000000000..78565473a --- /dev/null +++ b/src/capture_filter/resize_utils.cpp @@ -0,0 +1,33 @@ +#include "capture_filter/resize_utils.h" + +int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv){ + int res = 0; + + if (indata == NULL || outdata == NULL || data_lent == NULL || opencv == NULL) { + return 1; + } + + opencv->in.data = indata; + opencv->out.data = outdata; + + cvtColor(opencv->in, opencv->out, CV_YUV2RGB_UYVY); + resize(out, out, Size(0,0), opencv->scale_factor, opencv->scale_factor, INTER_LINEAR); + + *data_len = out.step * out.rows * sizeof(char); + + return res; +} + +int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact){ + int res = 0; + + if (opencv == NULL || width == 0 || height == 0 || scale_factor == 0) { + return 1; + } + + opencv->in = Mat.create(height, width, CV_8UC2); + opencv->width = width; + opencv->height = height; + + return 0; +} diff --git a/src/capture_filter/resize_utils.h b/src/capture_filter/resize_utils.h new file mode 100644 index 000000000..f083ea7b9 --- /dev/null +++ b/src/capture_filter/resize_utils.h @@ -0,0 +1,31 @@ +#ifndef RESIZE_UTILS_H_ +#define RESIZE_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + struct opencv_tile_struct { + int width; + int height; + float scale_factor; + Mat in, out; + }; + + int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv); + int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact); + +#ifdef __cplusplus +} +#endif + +#endif// RESIZE_UTILS_H_ From 1a89b2d61533eb3691ed400fef742434bf4849ba Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 17:44:01 +0100 Subject: [PATCH 35/57] extern c issues --- src/capture_filter/resize.c | 179 ---------------------------- src/capture_filter/resize_utils.cpp | 26 ++-- src/capture_filter/resize_utils.h | 18 +-- 3 files changed, 8 insertions(+), 215 deletions(-) delete mode 100644 src/capture_filter/resize.c diff --git a/src/capture_filter/resize.c b/src/capture_filter/resize.c deleted file mode 100644 index 45abd160d..000000000 --- a/src/capture_filter/resize.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * FILE: capture_filter/resize.c - * AUTHORS: Gerard Castillo - * Marc Palau - * - * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * - * This product includes software developed by the Fundació i2CAT, - * Internet I Innovació Digital a Catalunya. This product also includes - * software developed by CESNET z.s.p.o. - * - * 4. Neither the name of the University nor of the Institute may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" -#endif /* HAVE_CONFIG_H */ - -#include "capture_filter.h" - -#include "debug.h" - -#include "video.h" -#include "video_codec.h" - -#include "capture_filter/resize_utils.h" - -#define MAX_TILES 16 - -struct module; - -static int init(struct module *parent, const char *cfg, void **state); -static void done(void *state); -static struct video_frame *filter(void *state, struct video_frame *in); - -struct state_resize { - int num; - int denom; - int reinit; - struct video_frame *frame; - struct opencv_tile_struct **opencv; -}; - -static void usage() { - printf("\nUp/Downscaling by scale factor:\n\n"); - printf("resize usage:\n"); - printf("\tresize:numerator[/denominator]\n\n"); - printf("Downscaling example: resize:2 - downscale input frame size by scale factor of 2\n"); - printf("Upscaling example: resize:1/2 - upscale input frame size by scale factor of 2\n"); -} - -static int init(struct module *parent, const char *cfg, void **state) -{ - UNUSED(parent); - - int n; - int denom = 1;; - if(cfg) { - if(strcasecmp(cfg, "help") == 0) { - usage(); - return 1; - } - n = atoi(cfg); - if(strchr(cfg, '/')) { - denom = atoi(strchr(cfg, '/') + 1); - } - } else { - usage(); - return -1; - } - - if(n <= 0 || denom <= 0){ - printf("\n[RESIZE ERROR] numerator and denominator resize factors must be greater than zero!\n"); - usage(); - return -1; - } - - struct state_resize *s = calloc(1, sizeof(struct state_resize)); - s->reinit = 0; - s->num = n; - s->denom = denom; - s->frame = vf_alloc(MAX_TILES); - s->opencv = calloc(MAX_TILES, sizeof(struct opencv_tile_struct*)); - - *state = s; - return 0; -} - -static void done(void *state) -{ - struct state_resize *s = state; - - vf_free(s->frame); - free(state); -} - - - -static struct video_frame *filter(void *state, struct video_frame *in) -{ - struct state_resize *s = state; - int i, j; - int res = 0; - assert(in->tile_count <= MAX_TILES); - memcpy(s->frame, in, sizeof(struct video_frame)); - memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); - - if(s->reinit == 0){ - for(i=0; iframe->tile_count;i++){ - res = reconfigure_opencv_tile_struct(s->opencv[i], s->frame->tiles[i].width, s->frame->tiles[i].height, s->num, s->denom); - if(res!=0){ - printf("\n[RESIZE ERROR] error reconfiguring structs...\n"); - printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); - s->reinit = 1; - return in; - } - } - s->reinit = 1; - } - - for(i=0; iframe->tile_count;i++){ - - res = resize(in->tiles[i].data, s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->opencv[i]); - - if(res!=0){ - printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); - printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); - return in; - } - - s->frame->tiles[i].width *= s->num; - s->frame->tiles[i].width /= s->denom; - s->frame->tiles[i].height *= s->num; - s->frame->tiles[i].height /= s->denom; - } - - - return s->frame; -} - -struct capture_filter_info capture_filter_resize = { - .name = "resize", - .init = init, - .done = done, - .filter = filter, -}; - diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index 78565473a..c19e9e855 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -1,33 +1,21 @@ #include "capture_filter/resize_utils.h" -int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv){ +int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; + Mat out, in; if (indata == NULL || outdata == NULL || data_lent == NULL || opencv == NULL) { return 1; } - opencv->in.data = indata; - opencv->out.data = outdata; + in = Mat.create(height, width, CV_8UC2); + in.data = indata; + out.data = outdata; - cvtColor(opencv->in, opencv->out, CV_YUV2RGB_UYVY); - resize(out, out, Size(0,0), opencv->scale_factor, opencv->scale_factor, INTER_LINEAR); + cvtColor(in, out, CV_YUV2RGB_UYVY); + resize(out, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); *data_len = out.step * out.rows * sizeof(char); return res; } - -int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact){ - int res = 0; - - if (opencv == NULL || width == 0 || height == 0 || scale_factor == 0) { - return 1; - } - - opencv->in = Mat.create(height, width, CV_8UC2); - opencv->width = width; - opencv->height = height; - - return 0; -} diff --git a/src/capture_filter/resize_utils.h b/src/capture_filter/resize_utils.h index f083ea7b9..abd4d0769 100644 --- a/src/capture_filter/resize_utils.h +++ b/src/capture_filter/resize_utils.h @@ -10,22 +10,6 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - - struct opencv_tile_struct { - int width; - int height; - float scale_factor; - Mat in, out; - }; - - int resize(char *indata, char *outdata, unsigned int *data_len, struct opencv_tile_struct *opencv); - int reconfigure_opencv_tile_struct(struct opencv_tile_struct *opencv,unsigned int width, unsigned int height, float sc_fact); - -#ifdef __cplusplus -} -#endif +int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor); #endif// RESIZE_UTILS_H_ From 88757f1e16a041dff91f5587c552be2511f0a5f3 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 17:46:01 +0100 Subject: [PATCH 36/57] add resize cpp file --- src/capture_filter/resize.cpp | 172 ++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/capture_filter/resize.cpp diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp new file mode 100644 index 000000000..e88a85a5c --- /dev/null +++ b/src/capture_filter/resize.cpp @@ -0,0 +1,172 @@ +/* + * FILE: capture_filter/resize.c + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif /* HAVE_CONFIG_H */ + +#include "capture_filter/resize_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "capture_filter.h" + +#include "debug.h" + +#include "video.h" +#include "video_codec.h" + +#define MAX_TILES 16 + +struct module; + +static int init(struct module *parent, const char *cfg, void **state); +static void done(void *state); +static struct video_frame *filter(void *state, struct video_frame *in); + +struct state_resize { + int num; + int denom; + int reinit; + struct video_frame *frame; +}; + +static void usage() { + printf("\nUp/Downscaling by scale factor:\n\n"); + printf("resize usage:\n"); + printf("\tresize:numerator[/denominator]\n\n"); + printf("Downscaling example: resize:2 - downscale input frame size by scale factor of 2\n"); + printf("Upscaling example: resize:1/2 - upscale input frame size by scale factor of 2\n"); +} + +static int init(struct module *parent, const char *cfg, void **state) +{ + UNUSED(parent); + + int n; + int denom = 1;; + if(cfg) {reconfigure_opencv_tile_struct + if(strcasecmp(cfg, "help") == 0) { + usage(); + return 1; + } + n = atoi(cfg); + if(strchr(cfg, '/')) { + denom = atoi(strchr(cfg, '/') + 1); + } + } else { + usage(); + return -1; + } + + if(n <= 0 || denom <= 0){ + printf("\n[RESIZE ERROR] numerator and denominator resize factors must be greater than zero!\n"); + usage(); + return -1; + } + + struct state_resize *s = calloc(1, sizeof(struct state_resize)); + s->reinit = 0; + s->num = n; + s->denom = denom; + s->frame = vf_alloc(MAX_TILES); + s->opencv = calloc(MAX_TILES, sizeof(struct opencv_tile_struct*)); + + *state = s; + return 0; +} + +static void done(void *state) +{ + struct state_resize *s = state; + + vf_free(s->frame); + free(state); +} + + + +static struct video_frame *filter(void *state, struct video_frame *in) +{ + struct state_resize *s = state; + int i, j; + int res = 0; + assert(in->tile_count <= MAX_TILES); + memcpy(s->frame, in, sizeof(struct video_frame)); + memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); + + for(i=0; iframe->tile_count;i++){ + + res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->frame->tiles[i].width, s->frame->tiles[i].height, (double)s->num/s->denom); + + if(res!=0){ + printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); + printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); + return in; + } + + s->frame->tiles[i].width *= s->num; + s->frame->tiles[i].width /= s->denom; + s->frame->tiles[i].height *= s->num; + s->frame->tiles[i].height /= s->denom; + } + + + return s->frame; +} + +struct capture_filter_info capture_filter_resize = { + .name = "resize", + .init = init, + .done = done, + .filter = filter, +}; + +#ifdef __cplusplus +} +#endif From 7666e3eb308c5288863efd433c2a62c7e2685a79 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 17:52:00 +0100 Subject: [PATCH 37/57] solved c to cpp translates --- src/capture_filter/resize.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index e88a85a5c..b01d1227a 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -90,7 +90,7 @@ static int init(struct module *parent, const char *cfg, void **state) int n; int denom = 1;; - if(cfg) {reconfigure_opencv_tile_struct + if(cfg) { if(strcasecmp(cfg, "help") == 0) { usage(); return 1; @@ -110,12 +110,11 @@ static int init(struct module *parent, const char *cfg, void **state) return -1; } - struct state_resize *s = calloc(1, sizeof(struct state_resize)); + struct state_resize *s = (state_resize*) calloc(1, sizeof(struct state_resize)); s->reinit = 0; s->num = n; s->denom = denom; s->frame = vf_alloc(MAX_TILES); - s->opencv = calloc(MAX_TILES, sizeof(struct opencv_tile_struct*)); *state = s; return 0; @@ -123,7 +122,7 @@ static int init(struct module *parent, const char *cfg, void **state) static void done(void *state) { - struct state_resize *s = state; + struct state_resize *s = (state_resize*) state; vf_free(s->frame); free(state); @@ -133,7 +132,7 @@ static void done(void *state) static struct video_frame *filter(void *state, struct video_frame *in) { - struct state_resize *s = state; + struct state_resize *s = (state_resize*) state; int i, j; int res = 0; assert(in->tile_count <= MAX_TILES); @@ -142,7 +141,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ - res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, s->frame->tiles[i].data_len, s->frame->tiles[i].width, s->frame->tiles[i].height, (double)s->num/s->denom); + res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->frame->tiles[i].width, s->frame->tiles[i].height, (double)s->num/s->denom); if(res!=0){ printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); From bb0aa882c00c0df3f3f2b2f914bfbcd19505066b Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 18:07:31 +0100 Subject: [PATCH 38/57] static const problems cpp to c --- src/capture_filter/resize.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index b01d1227a..83160f483 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -133,7 +133,7 @@ static void done(void *state) static struct video_frame *filter(void *state, struct video_frame *in) { struct state_resize *s = (state_resize*) state; - int i, j; + unsigned int i; int res = 0; assert(in->tile_count <= MAX_TILES); memcpy(s->frame, in, sizeof(struct video_frame)); @@ -160,10 +160,10 @@ static struct video_frame *filter(void *state, struct video_frame *in) } struct capture_filter_info capture_filter_resize = { - .name = "resize", - .init = init, - .done = done, - .filter = filter, + "resize", + init, + done, + filter, }; #ifdef __cplusplus From f8f81934c3ca5197918e18dbc0a38c9e6d40362c Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 13 Mar 2014 18:13:07 +0100 Subject: [PATCH 39/57] name space defs --- src/capture_filter/resize_utils.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index c19e9e855..ced4ef623 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -1,10 +1,12 @@ #include "capture_filter/resize_utils.h" +using namespace cv; + int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; Mat out, in; - if (indata == NULL || outdata == NULL || data_lent == NULL || opencv == NULL) { + if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; } From 7914b60d725f68493827cf1e1dae24e1951ba23c Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 14 Mar 2014 13:47:26 +0100 Subject: [PATCH 40/57] compiling, now need to not destroy mat objects --- src/capture_filter/resize_utils.cpp | 10 ++++++---- src/capture_filter/resize_utils.h | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index ced4ef623..525820980 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -10,11 +10,13 @@ int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned i return 1; } - in = Mat.create(height, width, CV_8UC2); - in.data = indata; - out.data = outdata; + in.create(height, width, CV_8UC2); + in.data = (uchar*)indata; + out.data = (uchar*)outdata; - cvtColor(in, out, CV_YUV2RGB_UYVY); + printf("\nRESIZING!!!\n"); + + cvtColor(in, out, CV_YUV2RGB_Y422); resize(out, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); *data_len = out.step * out.rows * sizeof(char); diff --git a/src/capture_filter/resize_utils.h b/src/capture_filter/resize_utils.h index abd4d0769..12f34a8b1 100644 --- a/src/capture_filter/resize_utils.h +++ b/src/capture_filter/resize_utils.h @@ -7,8 +7,8 @@ #include "config_win32.h" #endif -#include -#include +#include +#include int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor); From feb248b6279be2fd1c5b109e7ba95f372333aab7 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 14 Mar 2014 14:37:00 +0100 Subject: [PATCH 41/57] resizing --- src/capture_filter/resize.cpp | 17 ++++++++++++----- src/capture_filter/resize_utils.cpp | 8 ++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 83160f483..d2ae03eb3 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -111,7 +111,7 @@ static int init(struct module *parent, const char *cfg, void **state) } struct state_resize *s = (state_resize*) calloc(1, sizeof(struct state_resize)); - s->reinit = 0; + s->reinit = 1; s->num = n; s->denom = denom; s->frame = vf_alloc(MAX_TILES); @@ -147,12 +147,19 @@ static struct video_frame *filter(void *state, struct video_frame *in) printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); return in; + }else{ + s->frame->color_spec = RGB; + s->frame->codec = RGB; } - s->frame->tiles[i].width *= s->num; - s->frame->tiles[i].width /= s->denom; - s->frame->tiles[i].height *= s->num; - s->frame->tiles[i].height /= s->denom; + + if(s->reinit==1){ + s->frame->tiles[i].width *= s->num; + s->frame->tiles[i].width /= s->denom; + s->frame->tiles[i].height *= s->num; + s->frame->tiles[i].height /= s->denom; + s->reinit = 0; + } } diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index 525820980..d043fd7da 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -4,7 +4,7 @@ using namespace cv; int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; - Mat out, in; + Mat out, in, rgb; if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; @@ -14,10 +14,10 @@ int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned i in.data = (uchar*)indata; out.data = (uchar*)outdata; - printf("\nRESIZING!!!\n"); + //printf("\nRESIZING by %f!!!\n",scale_factor ); - cvtColor(in, out, CV_YUV2RGB_Y422); - resize(out, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + cvtColor(in, rgb, CV_YUV2RGB_Y422); + resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); *data_len = out.step * out.rows * sizeof(char); From b25d0e2147f5596dfa89f77c06625dc87e9190f1 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Fri, 14 Mar 2014 14:49:22 +0100 Subject: [PATCH 42/57] resize with no proper colors, test bench implemented,todo --- src/capture_filter/resize.cpp | 4 ++-- src/capture_filter/resize_utils.cpp | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index d2ae03eb3..1e9d7f86b 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -148,8 +148,8 @@ static struct video_frame *filter(void *state, struct video_frame *in) printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); return in; }else{ - s->frame->color_spec = RGB; - s->frame->codec = RGB; + //s->frame->color_spec = RGB; + //s->frame->codec = RGB; } diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index d043fd7da..c38e72831 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -1,6 +1,7 @@ #include "capture_filter/resize_utils.h" using namespace cv; +FILE *F_save=NULL; int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; @@ -16,10 +17,21 @@ int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned i //printf("\nRESIZING by %f!!!\n",scale_factor ); - cvtColor(in, rgb, CV_YUV2RGB_Y422); + cvtColor(in, rgb, CV_YUV2RGB_Y422); //CV_YUV2RGB_UYVY resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); *data_len = out.step * out.rows * sizeof(char); + //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX + //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. + if(F_save==NULL){ + printf("recording resized...\n"); + F_save=fopen("rgb.raw", "wb"); + } + + //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); + fwrite(outdata,*data_len,1,F_save); + //FI CAPTURA + return res; } From fe718f62244e6360fb819e924e90571f96182f4b Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Tue, 18 Mar 2014 09:45:53 +0100 Subject: [PATCH 43/57] to test resizing flag from opencv api --- src/capture_filter/resize.cpp | 27 +++++++++++++++------------ src/capture_filter/resize_utils.cpp | 20 ++++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 1e9d7f86b..3495860b2 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -77,11 +77,11 @@ struct state_resize { }; static void usage() { - printf("\nUp/Downscaling by scale factor:\n\n"); + printf("\nDownscaling by scale factor:\n\n"); printf("resize usage:\n"); printf("\tresize:numerator[/denominator]\n\n"); - printf("Downscaling example: resize:2 - downscale input frame size by scale factor of 2\n"); - printf("Upscaling example: resize:1/2 - upscale input frame size by scale factor of 2\n"); + printf("Downscaling example: resize:1/2 - downscale input frame size by scale factor of 2\n"); + //printf("Upscaling example: resize:2 - upscale input frame size by scale factor of 2\n"); } static int init(struct module *parent, const char *cfg, void **state) @@ -109,6 +109,11 @@ static int init(struct module *parent, const char *cfg, void **state) usage(); return -1; } + if(n/denom > 1.0){ + printf("\n[RESIZE ERROR] numerator and denominator resize factors must be lower than 1 (only downscaling is supported)\n"); + usage(); + return -1; + } struct state_resize *s = (state_resize*) calloc(1, sizeof(struct state_resize)); s->reinit = 1; @@ -140,6 +145,13 @@ static struct video_frame *filter(void *state, struct video_frame *in) memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); for(i=0; iframe->tile_count;i++){ + if(s->reinit==1){ + s->frame->tiles[i].width *= s->num; + s->frame->tiles[i].width /= s->denom; + s->frame->tiles[i].height *= s->num; + s->frame->tiles[i].height /= s->denom; + s->reinit = 0; + } res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->frame->tiles[i].width, s->frame->tiles[i].height, (double)s->num/s->denom); @@ -151,15 +163,6 @@ static struct video_frame *filter(void *state, struct video_frame *in) //s->frame->color_spec = RGB; //s->frame->codec = RGB; } - - - if(s->reinit==1){ - s->frame->tiles[i].width *= s->num; - s->frame->tiles[i].width /= s->denom; - s->frame->tiles[i].height *= s->num; - s->frame->tiles[i].height /= s->denom; - s->reinit = 0; - } } diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index c38e72831..713466d94 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -22,16 +22,16 @@ int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned i *data_len = out.step * out.rows * sizeof(char); - //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX - //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. - if(F_save==NULL){ - printf("recording resized...\n"); - F_save=fopen("rgb.raw", "wb"); - } - - //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); - fwrite(outdata,*data_len,1,F_save); - //FI CAPTURA +// //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX +// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. +// if(F_save==NULL){ +// printf("recording resized...\n"); +// F_save=fopen("rgb.raw", "wb"); +// } +// +// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); +// fwrite(outdata,*data_len,1,F_save); +// //FI CAPTURA return res; } From 5a184cc3befa3d8d46403bfa901a2ceac62e15de Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Mon, 24 Mar 2014 14:20:51 +0100 Subject: [PATCH 44/57] rtp timeout checker for rtsp server increased to 35s --- src/rtsp/BasicRTSPOnlyServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtsp/BasicRTSPOnlyServer.cpp b/src/rtsp/BasicRTSPOnlyServer.cpp index 6712324e5..cd0f11f2b 100644 --- a/src/rtsp/BasicRTSPOnlyServer.cpp +++ b/src/rtsp/BasicRTSPOnlyServer.cpp @@ -83,7 +83,7 @@ int BasicRTSPOnlyServer::init_server() { } //setting livenessTimeoutTask - unsigned reclamationTestSeconds = 25; + unsigned reclamationTestSeconds = 35; TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); From 46124057441f9b9fd3d34c65f343c86a92162673 Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Tue, 25 Mar 2014 15:57:20 +0100 Subject: [PATCH 45/57] wokring with incorrect cast uchar to char --- src/capture_filter/resize.cpp | 24 ++++++++++++++++++++--- src/capture_filter/resize_utils.cpp | 30 +++++++++++++++-------------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 3495860b2..fe92b775e 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -63,6 +63,9 @@ extern "C" { #define MAX_TILES 16 +//FILE *F_save=NULL; + + struct module; static int init(struct module *parent, const char *cfg, void **state); @@ -71,6 +74,8 @@ static struct video_frame *filter(void *state, struct video_frame *in); struct state_resize { int num; + int orig_width; + int orig_height; int denom; int reinit; struct video_frame *frame; @@ -146,25 +151,38 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ if(s->reinit==1){ + s->orig_width = s->frame->tiles[i].width; + s->orig_height = s->frame->tiles[i].height; s->frame->tiles[i].width *= s->num; s->frame->tiles[i].width /= s->denom; s->frame->tiles[i].height *= s->num; s->frame->tiles[i].height /= s->denom; + s->frame->color_spec = RGB; s->reinit = 0; } - res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->frame->tiles[i].width, s->frame->tiles[i].height, (double)s->num/s->denom); + res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, (double)s->num/s->denom); if(res!=0){ printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); return in; }else{ - //s->frame->color_spec = RGB; - //s->frame->codec = RGB; + s->frame->color_spec = RGB; + s->frame->codec = RGB; } } + // //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX +// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. +// if(F_save==NULL){ +// printf("recording resized...\n"); +// F_save=fopen("rgb.raw", "wb"); +// } +// +// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); +// fwrite(s->frame->tiles[0].data, s->frame->tiles[0].data_len,1,F_save); + // //FI CAPTURA return s->frame; } diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index 713466d94..451fa1287 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -1,7 +1,8 @@ #include "capture_filter/resize_utils.h" using namespace cv; -FILE *F_save=NULL; + +//FILE *F_save=NULL; int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; @@ -10,28 +11,29 @@ int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned i if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; } + //printf("\nRESIZING by %f!!! (inputs: width: %d - height: %d)\n",scale_factor, width,height ); in.create(height, width, CV_8UC2); in.data = (uchar*)indata; out.data = (uchar*)outdata; - //printf("\nRESIZING by %f!!!\n",scale_factor ); - - cvtColor(in, rgb, CV_YUV2RGB_Y422); //CV_YUV2RGB_UYVY + cvtColor(in, rgb, CV_YUV2RGB_UYVY); //CV_YUV2RGB_UYVY resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); - *data_len = out.step * out.rows * sizeof(char); -// //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX -// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. -// if(F_save==NULL){ -// printf("recording resized...\n"); -// F_save=fopen("rgb.raw", "wb"); -// } + // //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX +// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. +// if(F_save==NULL){ +// printf("recording resized...\n"); +// F_save=fopen("rgb.raw", "wb"); +// } // -// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); -// fwrite(outdata,*data_len,1,F_save); -// //FI CAPTURA +// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); +// fwrite(outdata, *data_len,1,F_save); + // //FI CAPTURA + + + return res; } From 027cf4ee20fb5ef2ba2aa6d78f8d5cae6474da6b Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Fri, 28 Mar 2014 22:18:03 +0100 Subject: [PATCH 46/57] configure clean up --- config.guess | 1253 ++++++++++++++++++++++++++++++-------------------- config.sub | 642 ++++++++++++++++++++------ configure.ac | 4 +- install-sh | 677 +++++++++++++++++++-------- missing | 459 +++++++----------- 5 files changed, 1876 insertions(+), 1159 deletions(-) diff --git a/config.guess b/config.guess index ed2e03b7f..b79252d6b 100755 --- a/config.guess +++ b/config.guess @@ -1,13 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright 1992-2013 Free Software Foundation, Inc. -timestamp='2002-03-20' +timestamp='2013-06-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -16,24 +15,22 @@ timestamp='2002-03-20' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches with a ChangeLog entry to config-patches@gnu.org. -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` @@ -53,8 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -66,11 +62,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -88,30 +84,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -124,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + ;; +esac + # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -142,9 +171,11 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched @@ -153,7 +184,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -163,145 +194,139 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" - exit 0 ;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - macppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvmeppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mipseb-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sun3:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix - exit 0 ;; + exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 - exit 0 ;; + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; + exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos - exit 0 ;; + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -309,25 +334,51 @@ EOF else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -336,10 +387,10 @@ EOF esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; + exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 @@ -351,10 +402,10 @@ EOF echo sparc-sun-sunos${UNAME_RELEASE} ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -364,38 +415,41 @@ EOF # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -419,30 +473,36 @@ EOF exit (-1); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -455,29 +515,29 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` @@ -485,7 +545,7 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build @@ -500,16 +560,19 @@ EOF exit(0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; - *:AIX:*:[45]) + exit ;; + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -522,28 +585,28 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; + exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in @@ -552,64 +615,84 @@ EOF 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + esac ;; + esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -637,160 +720,176 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; + exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; + exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - x86:Interix*:3*) - echo i386-pc-interix3 - exit 0 ;; + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; + echo i586-pc-interix + exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin - exit 0 ;; + exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - rm -f $dummy.c - test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -800,102 +899,166 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el #else - #ifdef __INTEL_COMPILER - LIBC=gnu + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} #else - LIBC=gnuaout + CPU= #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c - test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + or1k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -903,99 +1066,113 @@ EOF else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 - exit 0 ;; + exit ;; paragon:*:*:*) echo i860-intel-osf1 - exit 0 ;; + exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` @@ -1003,61 +1180,99 @@ EOF else echo ns32k-sni-sysv fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos - exit 0 ;; + exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then @@ -1065,22 +1280,28 @@ EOF UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; - NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 @@ -1091,41 +1312,55 @@ EOF UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *:ITS:*:*) echo pdp10-unknown-its - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - eval $set_cc_for_build cat >$dummy.c < printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); + printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) @@ -1241,12 +1476,12 @@ main () } EOF -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) @@ -1255,22 +1490,22 @@ then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd - exit 0 ;; + exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; c34*) echo c34-convex-bsd - exit 0 ;; + exit ;; c38*) echo c38-convex-bsd - exit 0 ;; + exit ;; c4*) echo c4-convex-bsd - exit 0 ;; + exit ;; esac fi @@ -1281,7 +1516,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - ftp://ftp.gnu.org/pub/gnu/config/ + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/config.sub b/config.sub index f3657978c..9633db704 100755 --- a/config.sub +++ b/config.sub @@ -1,42 +1,40 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright 1992-2013 Free Software Foundation, Inc. -timestamp='2002-03-07' +timestamp='2013-08-10' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - +# along with this program; if not, see . +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. + +# Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -70,8 +68,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -83,11 +80,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -99,7 +96,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit 0;; + exit ;; * ) break ;; @@ -118,10 +115,18 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -144,10 +149,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -162,13 +170,17 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -185,6 +197,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -202,6 +218,12 @@ case $os in -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; -lynx*) os=-lynxos ;; @@ -226,43 +248,106 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ | i370 | i860 | i960 | ia64 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el | mips64vr4300 \ - | mips64vr4300el | mips64vr5000 | mips64vr5000el \ - | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ - | mipsisa32 | mipsisa64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | openrisc | or32 \ + | open8 \ + | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ - | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic80 | tron \ - | v850 | v850e \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ - | x86 | xscale | xstormy16 | xtensa \ - | z8k) + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -278,43 +363,82 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ - | m32r-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ - | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ - | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ - | v850-* | v850e-* | vax-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -332,6 +456,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -346,6 +473,12 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -369,6 +502,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -377,10 +514,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -405,12 +567,27 @@ case $basic_machine in basic_machine=j90-cray os=-unicos ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; crds | unos) basic_machine=m68k-crds ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; @@ -433,6 +610,14 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx @@ -544,7 +729,6 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -583,6 +767,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -594,10 +786,21 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -611,10 +814,6 @@ case $basic_machine in mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; monitor) basic_machine=m68k-rom68k os=-coff @@ -627,10 +826,21 @@ case $basic_machine in basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -695,6 +905,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -702,9 +918,12 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; - or32 | or32-*) + openrisc | openrisc-*) basic_machine=or32-unknown - os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson @@ -722,55 +941,76 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; + pentium4) + basic_machine=i786-pc + ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown - ;; + ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; @@ -781,6 +1021,14 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -801,6 +1049,20 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; @@ -808,6 +1070,12 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks @@ -826,6 +1094,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -866,7 +1137,7 @@ case $basic_machine in sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; - sv1) + sv1) basic_machine=sv1-cray os=-unicos ;; @@ -874,10 +1145,6 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; - t3d) - basic_machine=alpha-cray - os=-unicos - ;; t3e) basic_machine=alphaev5-cray os=-unicos @@ -886,9 +1153,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -903,6 +1170,10 @@ case $basic_machine in tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -924,8 +1195,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -946,13 +1217,16 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt + xbox) + basic_machine=i686-pc + os=-mingw32 ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos @@ -961,6 +1235,10 @@ case $basic_machine in basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -980,6 +1258,9 @@ case $basic_machine in romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -996,16 +1277,13 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1020,10 +1298,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1050,9 +1324,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1073,24 +1350,31 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1102,16 +1386,21 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; @@ -1124,6 +1413,9 @@ case $os in -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; @@ -1145,6 +1437,9 @@ case $os in -atheos*) os=-atheos ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; @@ -1155,7 +1450,7 @@ case $os in os=-rtmk-nova ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1167,6 +1462,9 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; @@ -1194,8 +1492,19 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) ;; -none) ;; @@ -1219,6 +1528,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1228,11 +1543,29 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1246,19 +1579,22 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; + or1k-*) + os=-elf + ;; or32-*) os=-coff ;; @@ -1271,9 +1607,15 @@ case $basic_machine in *-be) os=-beos ;; + *-haiku) + os=-haiku + ;; *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; @@ -1325,19 +1667,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1376,7 +1718,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1406,10 +1748,16 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) @@ -1433,7 +1781,7 @@ case $basic_machine in esac echo $basic_machine$os -exit 0 +exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/configure.ac b/configure.ac index 2c94c3df6..450f73a1c 100644 --- a/configure.ac +++ b/configure.ac @@ -1272,9 +1272,9 @@ case $host in then AC_DEFINE([HAVE_RTSP_SERVER], [1], [RTSP server build with live555 support]) SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" + CFLAGS="$CFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" SAVED_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" + CXXFLAGS="$CXXFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" RTSP_SERVER_INC= RTSP_SERVER_LIB="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock" RTSP_SERVER_OBJ="src/rtsp/c_basicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlySubsession.o" diff --git a/install-sh b/install-sh index e8436696c..377bb8687 100755 --- a/install-sh +++ b/install-sh @@ -1,250 +1,527 @@ #!/bin/sh -# # install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. # -# Copyright 1991 by the Massachusetts Institute of Technology +# Copyright (C) 1994 X Consortium # -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it +# 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. +# from scratch. +nl=' +' +IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec else - true + doit_exec=$doit fi -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else +# Put in absolute file names if you don't have them in your path; +# or use environment vars. -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } ' -IFS="${IFS-${defaultIFS}}" -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" +posix_mkdir= -pathcomp='' +# Desired mode of installed file. +mode=0755 -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi +src= +dst= +dir_arg= +dst_arg= - pathcomp="${pathcomp}/" +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done fi -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 -# If we're going to rename the final executable, determine the name now. + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename + mkdir_mode= fi -# don't allow the sed command to completely eliminate the filename + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= else - true + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi fi + prefix=$prefix/ + done -# Make a temp file name in the proper directory. + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi - dsttmp=$dstdir/#inst.$$# + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else -# Move or copy the file name to the temp name + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ - $doit $instcmd $src $dsttmp && + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap "rm -f ${dsttmp}" 0 && + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && -# and set any options; do chmod last to preserve setuid bits + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && -# Now rename the file to the real destination. + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && -fi && + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + trap '' 0 + fi +done -exit 0 +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/missing b/missing index e7ef83a1c..cdea51493 100755 --- a/missing +++ b/missing @@ -1,11 +1,10 @@ #! /bin/sh -# Common stub for a few missing GNU programs while installing. +# Common wrapper for a few potentially missing GNU programs. -scriptversion=2003-09-02.23 +scriptversion=2012-06-26.16; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 -# Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,9 +17,7 @@ scriptversion=2003-09-02.23 # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -28,333 +25,191 @@ scriptversion=2003-09-02.23 # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "Try '$0 --help' for more information" exit 1 fi -run=: +case $1 in -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; -msg="missing on your system" - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. Send bug reports to ." + exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" + exit $? ;; -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; - aclocal*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; esac -exit 0 +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'automa4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" # End: From d25720ad90b8e340fb04e1722f210388c9171eb9 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Mon, 31 Mar 2014 13:18:12 +0200 Subject: [PATCH 47/57] nal parser error issue implemented --- src/transmit.c | 20 ++++++++++---------- src/video_capture/rtsp.c | 13 ------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/transmit.c b/src/transmit.c index 3d92c5cc7..b3c9ac693 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -837,10 +837,10 @@ int rtpenc_h264_parse_nal_units(uint8_t *buf_in, int size, static uint8_t *rtpenc_h264_find_startcode_internal(uint8_t *start, uint8_t *end) { - uint8_t *p = start; - uint8_t *pend = end; // - 3; // XXX: w/o -3, p[1] and p[2] may fail. + //uint8_t *p = start; + //uint8_t *pend = end; // - 3; // XXX: w/o -3, p[1] and p[2] may fail. - for (p = start; p < pend; p++) { + for (uint8_t *p = start; p < end; p++) { if (p[0] == 0 && p[1] == 0 && p[2] == 1) { return p; } @@ -885,13 +885,14 @@ int rtpenc_h264_parse_nal_units(uint8_t *buf_in, int size, } int nal_size = nal_end - nal_start; - size += nal_size; + if(nal_size > 4){ + size += nal_size; + nals[(*nnals)].data = nal_start; + nals[(*nnals)].size = nal_size; + (*nnals)++; - nals[(*nnals)].data = nal_start; - nals[(*nnals)].size = nal_size; - (*nnals)++; - - nal_start = nal_end; + nal_start = nal_end; + }else nal_start += 3; } return size; } @@ -1022,7 +1023,6 @@ static void tx_send_base_h264(struct tx *tx, struct tile *tile, struct rtp *rtp_ } } else { - uint8_t frag_header[2]; int frag_header_size = 2; diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index 59b24edf6..77ed782fe 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -386,20 +386,7 @@ vidcap_rtsp_grab(void *state, struct audio_frame **audio) { s->vrtsp_state->frame->tiles[0].data = s->vrtsp_state->frame->h264_buffer; if(s->vrtsp_state->frame->h264_offset_len>0 && s->vrtsp_state->frame->h264_frame_type == INTRA){ - if(s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len] == 0 && - s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+1] == 0 && - s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+2] == 0 && - s->vrtsp_state->frame->tiles[0].data[s->vrtsp_state->frame->h264_offset_len+3] == 1 ){ - - memcpy(tmp, s->vrtsp_state->frame->tiles[0].data+4,s->vrtsp_state->frame->tiles[0].data_len-4); - memcpy(tmp, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len-4); - s->vrtsp_state->frame->tiles[0].data_len-=4; - memcpy(s->vrtsp_state->frame->tiles[0].data, tmp, s->vrtsp_state->frame->tiles[0].data_len); - - } - else{ memcpy(s->vrtsp_state->frame->tiles[0].data, s->vrtsp_state->frame->h264_offset_buffer, s->vrtsp_state->frame->h264_offset_len); - } } if (s->vrtsp_state->decompress) { From 0bca45a4584ee129b92f491f2c4011a9103fafd3 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Thu, 10 Apr 2014 11:58:14 +0200 Subject: [PATCH 48/57] livemedia configure changed to default compiled version - not from repo --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 450f73a1c..6e2d29472 100644 --- a/configure.ac +++ b/configure.ac @@ -1266,15 +1266,15 @@ AC_ARG_ENABLE(rtsp_server, case $host in *-linux-*) - AC_CHECK_FILE(/usr/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no]) + AC_CHECK_FILE(/usr/local/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no]) if test $rtsp_server_req != no -a $FOUND_LIVE_H = yes then AC_DEFINE([HAVE_RTSP_SERVER], [1], [RTSP server build with live555 support]) SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" + CFLAGS="$CFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" SAVED_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" + CXXFLAGS="$CXXFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" RTSP_SERVER_INC= RTSP_SERVER_LIB="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock" RTSP_SERVER_OBJ="src/rtsp/c_basicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlySubsession.o" From a34a0ee23d2bcd0049a1204b19a3aa673f3c79a0 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Thu, 10 Apr 2014 14:37:56 +0200 Subject: [PATCH 49/57] capture filter 1rst release: todo with other color specs... --- src/capture_filter/resize.cpp | 33 +++++++++-------------------- src/capture_filter/resize_utils.cpp | 28 ++++++------------------ src/capture_filter/resize_utils.h | 4 +++- 3 files changed, 19 insertions(+), 46 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index fe92b775e..39abb67d8 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -63,9 +63,6 @@ extern "C" { #define MAX_TILES 16 -//FILE *F_save=NULL; - - struct module; static int init(struct module *parent, const char *cfg, void **state); @@ -84,9 +81,8 @@ struct state_resize { static void usage() { printf("\nDownscaling by scale factor:\n\n"); printf("resize usage:\n"); - printf("\tresize:numerator[/denominator]\n\n"); + printf("\tresize:numerator/denominator\n\n"); printf("Downscaling example: resize:1/2 - downscale input frame size by scale factor of 2\n"); - //printf("Upscaling example: resize:2 - upscale input frame size by scale factor of 2\n"); } static int init(struct module *parent, const char *cfg, void **state) @@ -124,7 +120,6 @@ static int init(struct module *parent, const char *cfg, void **state) s->reinit = 1; s->num = n; s->denom = denom; - s->frame = vf_alloc(MAX_TILES); *state = s; return 0; @@ -146,8 +141,11 @@ static struct video_frame *filter(void *state, struct video_frame *in) unsigned int i; int res = 0; assert(in->tile_count <= MAX_TILES); - memcpy(s->frame, in, sizeof(struct video_frame)); - memcpy(s->frame->tiles, in->tiles, in->tile_count * sizeof(struct tile)); + + if(s->reinit==1){ + struct video_desc desc = video_desc_from_frame(in); + s->frame = vf_alloc_desc_data(desc); + } for(i=0; iframe->tile_count;i++){ if(s->reinit==1){ @@ -161,29 +159,18 @@ static struct video_frame *filter(void *state, struct video_frame *in) s->reinit = 0; } - res = resize_frame(in->tiles[i].data, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, (double)s->num/s->denom); + res = resize_frame(in->tiles[i].data, in->color_spec, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, (double)s->num/s->denom); if(res!=0){ - printf("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); - printf("\t\t No scale factor applied at all. Bypassing original frame.\n"); - return in; + error_msg("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); + error_msg("\t\t No scale factor applied at all. No frame returns...\n"); + return NULL; }else{ s->frame->color_spec = RGB; s->frame->codec = RGB; } } - // //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX -// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. -// if(F_save==NULL){ -// printf("recording resized...\n"); -// F_save=fopen("rgb.raw", "wb"); -// } -// -// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); -// fwrite(s->frame->tiles[0].data, s->frame->tiles[0].data_len,1,F_save); - // //FI CAPTURA - return s->frame; } diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index 451fa1287..f6619845d 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -2,38 +2,22 @@ using namespace cv; -//FILE *F_save=NULL; - -int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ +int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; Mat out, in, rgb; - + assert(in_color == UYVY); if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; } - //printf("\nRESIZING by %f!!! (inputs: width: %d - height: %d)\n",scale_factor, width,height ); in.create(height, width, CV_8UC2); in.data = (uchar*)indata; - out.data = (uchar*)outdata; - cvtColor(in, rgb, CV_YUV2RGB_UYVY); //CV_YUV2RGB_UYVY - resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + cvtColor(in, rgb, CV_YUV2RGB_UYVY); + resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + *data_len = out.step * out.rows * sizeof(char); - - // //MODUL DE CAPTURA AUDIO A FITXER PER COMPROVACIONS EN TX -// //CAPTURA FRAMES ABANS DE DESCODIFICAR PER COMPROVAR RECEPCIÓ. -// if(F_save==NULL){ -// printf("recording resized...\n"); -// F_save=fopen("rgb.raw", "wb"); -// } -// -// //fwrite(tx_frame->audio_data,tx_frame->audio_data_len,1,F_audio_tx_embed_BM); -// fwrite(outdata, *data_len,1,F_save); - // //FI CAPTURA - - - + memcpy(outdata,out.data,*data_len); return res; } diff --git a/src/capture_filter/resize_utils.h b/src/capture_filter/resize_utils.h index 12f34a8b1..716e50663 100644 --- a/src/capture_filter/resize_utils.h +++ b/src/capture_filter/resize_utils.h @@ -9,7 +9,9 @@ #include #include +#include "types.h" -int resize_frame(char *indata, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor); + +int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor); #endif// RESIZE_UTILS_H_ From 6b5ab227716bce6b529618e2d576c2a8b491553c Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Thu, 10 Apr 2014 15:03:29 +0200 Subject: [PATCH 50/57] resize filter for UYVY and RGB --- src/capture_filter/resize_utils.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index f6619845d..84fad7cb4 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -5,16 +5,35 @@ using namespace cv; int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ int res = 0; Mat out, in, rgb; - assert(in_color == UYVY); + assert(in_color == UYVY || in_color == RGB); if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; } - in.create(height, width, CV_8UC2); - in.data = (uchar*)indata; + switch(in_color){ + case UYVY: + in.create(height, width, CV_8UC2); + in.data = (uchar*)indata; + cvtColor(in, rgb, CV_YUV2RGB_UYVY); + resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + break; + case RGB: + in.create(height, width, CV_8UC3); + in.data = (uchar*)indata; + resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + break; + case RGBA: + in.create(height, width, CV_8UC4); + in.data = (uchar*)indata; + resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + break; + case BGR: + in.create(height, width, CV_8UC3); + in.data = (uchar*)indata; + resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + break; + } - cvtColor(in, rgb, CV_YUV2RGB_UYVY); - resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); *data_len = out.step * out.rows * sizeof(char); memcpy(outdata,out.data,*data_len); From e1d788699a6de0d94a99e3b01a6595a6ef8fe846 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Thu, 10 Apr 2014 16:05:32 +0200 Subject: [PATCH 51/57] todo YUVY,RGBA and BGR --- src/capture_filter/resize.cpp | 2 + src/capture_filter/resize_utils.cpp | 59 +++++++++++++++++++++++------ src/capture_filter/resize_utils.h | 45 +++++++++++++++++++++- 3 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 39abb67d8..98b22cef0 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -149,6 +149,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ if(s->reinit==1){ + //TODO: all tiles could have different sizes and other color specs different than UYVY and RGB s->orig_width = s->frame->tiles[i].width; s->orig_height = s->frame->tiles[i].height; s->frame->tiles[i].width *= s->num; @@ -157,6 +158,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) s->frame->tiles[i].height /= s->denom; s->frame->color_spec = RGB; s->reinit = 0; + if(i==0) printf("[resize filter] resizing from %dx%d to %dx%d\n", in->tiles[i].width, in->tiles[i].height, s->frame->tiles[i].width, s->frame->tiles[i].height); } res = resize_frame(in->tiles[i].data, in->color_spec, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, (double)s->num/s->denom); diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index 84fad7cb4..a35885891 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -1,11 +1,57 @@ +/* + * FILE: capture_filter/resize_utils.cpp + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #include "capture_filter/resize_utils.h" using namespace cv; int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ + assert(in_color == UYVY || in_color == RGB); + int res = 0; Mat out, in, rgb; - assert(in_color == UYVY || in_color == RGB); + if (indata == NULL || outdata == NULL || data_len == NULL) { return 1; } @@ -19,22 +65,11 @@ int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *da break; case RGB: in.create(height, width, CV_8UC3); - in.data = (uchar*)indata; - resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); - break; - case RGBA: - in.create(height, width, CV_8UC4); - in.data = (uchar*)indata; - resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); - break; - case BGR: - in.create(height, width, CV_8UC3); in.data = (uchar*)indata; resize(in, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); break; } - *data_len = out.step * out.rows * sizeof(char); memcpy(outdata,out.data,*data_len); diff --git a/src/capture_filter/resize_utils.h b/src/capture_filter/resize_utils.h index 716e50663..b77629ea3 100644 --- a/src/capture_filter/resize_utils.h +++ b/src/capture_filter/resize_utils.h @@ -1,3 +1,47 @@ +/* + * FILE: capture_filter/resize_utils.c + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef RESIZE_UTILS_H_ #define RESIZE_UTILS_H_ @@ -11,7 +55,6 @@ #include #include "types.h" - int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor); #endif// RESIZE_UTILS_H_ From d5fe4fd2810382f11a55d6bb8bd6ce929ef36ff3 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Thu, 10 Apr 2014 16:19:56 +0200 Subject: [PATCH 52/57] some improvement due to division factor, maybe required port to opencv with cuda or opengl --- src/capture_filter/resize.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 98b22cef0..50eff5334 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -1,5 +1,5 @@ /* - * FILE: capture_filter/resize.c + * FILE: capture_filter/resize.cpp * AUTHORS: Gerard Castillo * Marc Palau * @@ -74,6 +74,7 @@ struct state_resize { int orig_width; int orig_height; int denom; + double scale_factor; int reinit; struct video_frame *frame; }; @@ -157,11 +158,12 @@ static struct video_frame *filter(void *state, struct video_frame *in) s->frame->tiles[i].height *= s->num; s->frame->tiles[i].height /= s->denom; s->frame->color_spec = RGB; + s->scale_factor = (double)s->num/s->denom; s->reinit = 0; if(i==0) printf("[resize filter] resizing from %dx%d to %dx%d\n", in->tiles[i].width, in->tiles[i].height, s->frame->tiles[i].width, s->frame->tiles[i].height); } - res = resize_frame(in->tiles[i].data, in->color_spec, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, (double)s->num/s->denom); + res = resize_frame(in->tiles[i].data, in->color_spec, s->frame->tiles[i].data, &s->frame->tiles[i].data_len, s->orig_width, s->orig_height, s->scale_factor); if(res!=0){ error_msg("\n[RESIZE ERROR] Unable to resize with scale factor configured [%d/%d] in tile number %d\n", s->num, s->denom, i); From ff5135dfff37ef70b2dbaa766d5b37551715d48f Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Tue, 15 Apr 2014 16:33:27 +0200 Subject: [PATCH 53/57] solved segfault when sending embedded audio as standard mulaw, now problem of processing input... --- src/audio/audio.c | 1 - src/transmit.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index 788632837..152ad832f 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -785,7 +785,6 @@ static void *audio_sender_thread(void *arg) } } }else if(s->sender == NET_STANDARD){ - //TODO audio_tx_send_mulaw // RESAMPLE resample(&resample_state, buffer); // COMPRESS diff --git a/src/transmit.c b/src/transmit.c index a113f73ff..166466af0 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -154,7 +154,7 @@ struct tx { // Mulaw audio memory reservation static void init_tx_mulaw_buffer() { if (!buffer_mulaw_init) { - data_buffer_mulaw = malloc(BUFFER_MTU_SIZE); + data_buffer_mulaw = malloc(BUFFER_MTU_SIZE*20); buffer_mulaw_init = 1; } } From 13feca417a41afed446ab08b9621cc59d8e31bb2 Mon Sep 17 00:00:00 2001 From: Gerard CL Date: Tue, 22 Apr 2014 09:02:52 +0200 Subject: [PATCH 54/57] audio tx mulaw to be continued --- src/transmit.c | 69 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/transmit.c b/src/transmit.c index 166466af0..937885112 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -761,6 +761,9 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer * audio_tx_send_mulaw - Send interleaved channels from the audio_frame2 at 1 bps, * as the mulaw standard. */ +FILE *F_send=NULL; +FILE *F_send2=NULL; + void audio_tx_send_mulaw(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer) { int pt; @@ -782,48 +785,48 @@ void audio_tx_send_mulaw(struct tx* tx, struct rtp *rtp_session, audio_frame2 * // The sizes for the different audio_frame2 channels must be the same. for (int i = 1 ; i < buffer->ch_count ; i++) assert(buffer->data_len[0] == buffer->data_len[i]); - int data_len = buffer->data_len[0] * buffer->ch_count; /* Number of samples to send (bps=1)*/ + int data_len = buffer->data_len[0] * buffer->ch_count * buffer->bps; /* Number of samples to send */ int data_remainig = data_len; - int payload_size = tx->mtu - 40; /* Max size of an RTP payload field */ - int packets = data_len / payload_size; - if (data_len % payload_size != 0) packets++; /* Number of RTP packets needed */ + int payload_size = tx->mtu - 40; /* Max size of an RTP payload field */ init_tx_mulaw_buffer(); char *curr_sample = data_buffer_mulaw; + int pointer = 0; - // For each interval that fits in an RTP payload field. - for (int p = 0 ; p < packets ; p++) { + int ch, pos = 0, count = 0, pointerToSend = 0; - int samples_per_packet; - int data_to_send; - if (data_remainig >= payload_size) { - samples_per_packet = payload_size / buffer->ch_count; - data_to_send = payload_size; - } - else { - samples_per_packet = data_remainig / buffer->ch_count; - data_to_send = data_remainig; - } + do{ + for(ch = 0; ch < buffer->ch_count; ch++){ + memcpy(curr_sample, buffer->data[ch] + pos, buffer->bps * sizeof(char)); + curr_sample += buffer->bps * sizeof(char); + count+=buffer->bps * sizeof(char); + data_remainig--; + } + pos += buffer->bps * sizeof(char); - // Interleave the samples - for (int ch_sample = 0 ; ch_sample < samples_per_packet ; ch_sample++){ - for (int ch = 0 ; ch < buffer->ch_count ; ch++) { - //TODO to be checked prepiously -> if(buffer->data[ch]!=NULL){ - memcpy(curr_sample, (char *)(buffer->data[ch] + ch_sample), sizeof(uint8_t)); - curr_sample += sizeof(uint8_t); - data_remainig--; - // } - } - } + if((pos * buffer->ch_count) % payload_size == 0){ + // Update first sample timestamp + timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/(buffer->bps * buffer->ch_count)))); - // Update first sample timestamp - timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/buffer->ch_count))); + // Send the packet + rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ + 0, /* contributing sources length */ + data_buffer_mulaw + pointerToSend, payload_size, + 0, 0, 0); + } + pointerToSend += count; - // Send the packet - rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ - 0, /* contributing sources length */ - data_buffer_mulaw, data_to_send, - 0, 0, 0); + }while(count < data_len); + + if(pos % payload_size != 0){ + // Update first sample timestamp + timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/(buffer->bps * buffer->ch_count)))); + + // Send the packet + rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ + 0, /* contributing sources length */ + data_buffer_mulaw+pointerToSend-(pos % payload_size) , pos % payload_size, + 0, 0, 0); } tx->buffer ++; From 2459fea96867fb1b134d96c2868a4153679bbe4d Mon Sep 17 00:00:00 2001 From: "gerard.castillo" Date: Wed, 23 Apr 2014 12:47:17 +0200 Subject: [PATCH 55/57] audio standard fully working --- src/transmit.c | 68 ++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/src/transmit.c b/src/transmit.c index 166466af0..42ac74eb0 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -379,7 +379,6 @@ void format_video_header(struct video_frame *frame, int tile_idx, int buffer_idx void tx_send_tile(struct tx *tx, struct video_frame *frame, int pos, struct rtp *rtp_session) { - struct tile *tile; int last = FALSE; uint32_t ts = 0; int fragment_offset = 0; @@ -389,7 +388,6 @@ tx_send_tile(struct tx *tx, struct video_frame *frame, int pos, struct rtp *rtp_ platform_spin_lock(&tx->spin); - tile = vf_get_tile(frame, pos); ts = get_local_mediatime(); if(frame->fragment && tx->last_frame_fragment_id == frame->frame_fragment_id) { @@ -772,7 +770,6 @@ void audio_tx_send_mulaw(struct tx* tx, struct rtp *rtp_session, audio_frame2 * // 8000 Hz, 1 channel is the ITU-T G.711 standard // More channels or Hz goes to DynRTP-Type97 -//TODO CHECK ACTUAL CHCOUNT IN ORDER TO PROPERLY CREATE PAYLOAD TYPE if (buffer->ch_count == 1 && buffer->sample_rate == 8000) { pt = PT_ITU_T_G711_PCMU; } else { @@ -782,50 +779,45 @@ void audio_tx_send_mulaw(struct tx* tx, struct rtp *rtp_session, audio_frame2 * // The sizes for the different audio_frame2 channels must be the same. for (int i = 1 ; i < buffer->ch_count ; i++) assert(buffer->data_len[0] == buffer->data_len[i]); - int data_len = buffer->data_len[0] * buffer->ch_count; /* Number of samples to send (bps=1)*/ + int data_len = buffer->data_len[0] * buffer->ch_count; /* Number of samples to send */ int data_remainig = data_len; - int payload_size = tx->mtu - 40; /* Max size of an RTP payload field */ - int packets = data_len / payload_size; - if (data_len % payload_size != 0) packets++; /* Number of RTP packets needed */ + int payload_size = tx->mtu - 40; /* Max size of an RTP payload field */ init_tx_mulaw_buffer(); char *curr_sample = data_buffer_mulaw; - // For each interval that fits in an RTP payload field. - for (int p = 0 ; p < packets ; p++) { + int ch, pos = 0, count = 0, pointerToSend = 0; - int samples_per_packet; - int data_to_send; - if (data_remainig >= payload_size) { - samples_per_packet = payload_size / buffer->ch_count; - data_to_send = payload_size; - } - else { - samples_per_packet = data_remainig / buffer->ch_count; - data_to_send = data_remainig; - } + do{ + for(ch = 0; ch < buffer->ch_count; ch++){ + memcpy(curr_sample, buffer->data[ch] + pos, buffer->bps * sizeof(char)); + curr_sample += buffer->bps * sizeof(char); + count+=buffer->bps * sizeof(char); + data_remainig--; + } + pos += buffer->bps * sizeof(char); - // Interleave the samples - for (int ch_sample = 0 ; ch_sample < samples_per_packet ; ch_sample++){ - for (int ch = 0 ; ch < buffer->ch_count ; ch++) { - //TODO to be checked prepiously -> if(buffer->data[ch]!=NULL){ - memcpy(curr_sample, (char *)(buffer->data[ch] + ch_sample), sizeof(uint8_t)); - curr_sample += sizeof(uint8_t); - data_remainig--; - // } - } - } + if((pos * buffer->ch_count) % payload_size == 0){ + // Update first sample timestamp + timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/(buffer->bps * buffer->ch_count)))); + // Send the packet + rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ + 0, /* contributing sources length */ + data_buffer_mulaw + pointerToSend, payload_size, + 0, 0, 0); + pointerToSend += payload_size; + } + }while(count < data_len); - // Update first sample timestamp - timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/buffer->ch_count))); - - // Send the packet - rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ - 0, /* contributing sources length */ - data_buffer_mulaw, data_to_send, - 0, 0, 0); + if((pos * buffer->ch_count) % payload_size != 0){ + // Update first sample timestamp + timestamp = get_std_audio_local_mediatime((buffer->data_len[0] - (data_remainig/(buffer->bps * buffer->ch_count)))); + // Send the packet + rtp_send_data(rtp_session, timestamp, pt, 0, 0, /* contributing sources */ + 0, /* contributing sources length */ + data_buffer_mulaw + pointerToSend , (pos * buffer->ch_count) % payload_size, + 0, 0, 0); } - tx->buffer ++; platform_spin_unlock(&tx->spin); From ba2052aadcc3108221c995408a71c95cb06c262f Mon Sep 17 00:00:00 2001 From: "gerard.castillo" Date: Wed, 23 Apr 2014 14:00:01 +0200 Subject: [PATCH 56/57] configure.ac for livemedia from repo --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 5a765ddb6..725a07a7f 100644 --- a/configure.ac +++ b/configure.ac @@ -1264,15 +1264,15 @@ AC_ARG_ENABLE(rtsp_server, case $host in *-linux-*) - AC_CHECK_FILE(/usr/local/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no]) + AC_CHECK_FILE(/usr/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no]) if test $rtsp_server_req != no -a $FOUND_LIVE_H = yes then AC_DEFINE([HAVE_RTSP_SERVER], [1], [RTSP server build with live555 support]) SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" + CFLAGS="$CFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" SAVED_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -I/usr/local/include/groupsock -I/usr/local/include/liveMedia -I/usr/local/include/BasicUsageEnvironment -I/usr/local/include/UsageEnvironment" + CXXFLAGS="$CXXFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment" RTSP_SERVER_INC= RTSP_SERVER_LIB="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock" RTSP_SERVER_OBJ="src/rtsp/c_basicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlySubsession.o" From 836de242a97b6e613606f1cd5ee0fc18ba1ae170 Mon Sep 17 00:00:00 2001 From: "gerard.castillo" Date: Wed, 23 Apr 2014 14:07:34 +0200 Subject: [PATCH 57/57] assert mu-law codec for audio tx std --- src/transmit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/transmit.c b/src/transmit.c index 3ad4874ce..f66c69717 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -761,6 +761,8 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer */ void audio_tx_send_mulaw(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer) { + assert(buffer->codec == AC_MULAW); + int pt; uint32_t timestamp;