diff options
author | naga <naga@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-03-22 05:48:46 +0000 |
---|---|---|
committer | naga <naga@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-03-22 05:48:46 +0000 |
commit | af1e2e53f6381dba517ad4d3d832083dcbff0e73 (patch) | |
tree | 61ab115e366e3aa50d42ac0943a811a5fe187083 /TAO | |
parent | 26e8b00da62be63ffe6f2e9211656a6b8df73d48 (diff) | |
download | ATCD-af1e2e53f6381dba517ad4d3d832083dcbff0e73.tar.gz |
*** empty log message ***
Diffstat (limited to 'TAO')
9 files changed, 2247 insertions, 927 deletions
diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.cpp index 0f888bff962..1cc160e3451 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.cpp +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.cpp @@ -8,8 +8,8 @@ * copyright notice and this permission notice appear in supporting * documentation, and that the name of O.G.I. not be used in advertising or * publicity pertaining to distribution of the software without specific, - * written prior permission. O.G.I. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" + * written prior permission. O.G.I. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * O.G.I. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING @@ -20,8 +20,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Shanwei Cen - * Department of Computer Science and Engineering - * email: scen@cse.ogi.edu + * Department of Computer Science and Engineering + * email: scen@cse.ogi.edu */ #include "Globals.h" @@ -31,8 +31,8 @@ int Mpeg_Global::listenSocketIn = -1; int Mpeg_Global::listenSocketUn = -1; struct linger Mpeg_Global::linger = {1,1}; int Mpeg_Global::live_audio = 0; -int Mpeg_Global::live_video = 0; /* 0 - no, 1 - to open, 2 - opened */ -int Mpeg_Global::drift_ppm = 0; /* clock drift in ppm */ +int Mpeg_Global::live_video = 0; /* 0 - no, 1 - to open, 2 - opened */ +int Mpeg_Global::drift_ppm = 0; /* clock drift in ppm */ int Mpeg_Global::session_limit = SESSION_NUM; int Mpeg_Global::session_num = 0; int Mpeg_Global::rttag = 0; @@ -44,282 +44,1975 @@ int Video_Timer_Global::timerOn = 0; int Video_Timer_Global::timerAdjust = 0; int Video_Timer_Global::preTimerVal = 0; -// initialize the nasty int's, doubles and their friends +// Initialize the nasty int's, doubles and their friends Video_Global::Video_Global () { - live_source = 0; - video_format = 0; - - pkts_sent = 0; - start_time = 0; - - conn_tag = 0; + live_source = 0; + video_format = 0; + + pkts_sent = 0; + start_time = 0; + + conn_tag = 0; - normalExit = 1; + normalExit = 1; - serviceSocket = 0; - videoSocket = -1; + serviceSocket = 0; + videoSocket = -1; - ACE_OS::memset (videoFile, - 0, - PATH_SIZE); + ACE_OS::memset (videoFile, + 0, + PATH_SIZE); - fp = 0; + fp = 0; - needHeader = 0; + needHeader = 0; - lastRef [0] = lastRef [1] = 0; + lastRef [0] = lastRef [1] = 0; - lastRefPtr = 0; - currentUPF = 0; - addedUPF = 0; - addedSignals = 0; - VStimeAdvance = 0; - fps = 0; /* current frames-per-second: playback speed */ - frameRateLimit = 0; + lastRefPtr = 0; + currentUPF = 0; + addedUPF = 0; + addedSignals = 0; + VStimeAdvance = 0; + fps = 0; /* current frames-per-second: playback speed */ + frameRateLimit = 0; - packet = 0; - packetBufSize = 0; - msgsn = 0; - packetsn = 0; - msgsize = 0; + packet = 0; + packetBufSize = 0; + msgsn = 0; + packetsn = 0; + msgsize = 0; - precmd = 0; - cmd = 0; - cmdsn = 0; - nextFrame = 0; - nextGroup = 0; - firstPatternSize = 0; - firstSendPattern = 0; - sendPatternGops = 0; - ACE_OS::memset (sendPattern, - 0, - PATTERN_SIZE); + precmd = 0; + cmd = 0; + cmdsn = 0; + nextFrame = 0; + nextGroup = 0; + firstPatternSize = 0; + firstSendPattern = 0; + sendPatternGops = 0; + ACE_OS::memset (sendPattern, + 0, + PATTERN_SIZE); #ifdef STAT - framesSent = 0; + framesSent = 0; #endif - fileSize = 0; - maxS = 0; - maxG = 0; - maxI = 0; - maxP = 0; - maxB = 0; - minS = 0x7fffffff; - minG = 0x7fffffff; - minI = 0x7fffffff; - minP = 0x7fffffff; - minB = 0x7fffffff; - - numS = 0; - numG = 0; - numF = 0; - numI = 0; - numP = 0; - numB = 0; - - averageFrameSize = 0; - horizontalSize = 0; - verticalSize = 0; - pelAspectRatio = 0; - pictureRate = 0; - vbvBufferSize = 0; - firstGopFrames = 0; - patternSize = 0; - - ACE_OS::memset (pattern, - 0, - PATTERN_SIZE); - - // struct pointers - systemHeader = 0; - - gopTable = 0; - - frameTable = 0; - - // playvideo local vars - - preGroup = -1; - preHeader = -1; - preFrame = -1; - - fast_preGroup = -1; - fast_preHeader= -1; + fileSize = 0; + maxS = 0; + maxG = 0; + maxI = 0; + maxP = 0; + maxB = 0; + minS = 0x7fffffff; + minG = 0x7fffffff; + minI = 0x7fffffff; + minP = 0x7fffffff; + minB = 0x7fffffff; + + numS = 0; + numG = 0; + numF = 0; + numI = 0; + numP = 0; + numB = 0; + + averageFrameSize = 0; + horizontalSize = 0; + verticalSize = 0; + pelAspectRatio = 0; + pictureRate = 0; + vbvBufferSize = 0; + firstGopFrames = 0; + patternSize = 0; + + ACE_OS::memset (pattern, + 0, + PATTERN_SIZE); + + // struct pointers + systemHeader = 0; + + gopTable = 0; + + frameTable = 0; + + // playvideo local vars + + preGroup = -1; + preHeader = -1; + preFrame = -1; + + fast_preGroup = -1; + fast_preHeader= -1; } -void -Video_Timer_Global::StartTimer (void) +int +Video_Global::FBread (char * buf, int size) { - VIDEO_SINGLETON::instance ()->addedUPF = 0; - VIDEO_SINGLETON::instance ()->addedSignals = 0; - timerAdjust = (VIDEO_SINGLETON::instance ()->VStimeAdvance * SPEEDUP_INV_SCALE) / VIDEO_SINGLETON::instance ()->currentUPF; - /* - SFprintf(stderr, "VS StartTimer(): fast-start frames %d\n", - timerAdjust / SPEEDUP_INV_SCALE); + int res; + while ( (res = (this->conn_tag >= 0 ? wait_read_bytes (this->videoSocket, buf, size) : + read (this->videoSocket, buf, size))) == -1) + { + if (errno == EINTR) {errno = 0; continue; } + if (errno == EPIPE || errno == ECONNRESET) exit (0); + perror ("VS reads Feedback this->packet"); + return -1; + } + if (res < size) { + if (res) fprintf (stderr, "VS warn: FBread () res %dB < size %dB\n", res, size); + return -1; + } + return 0; +} + +/* send a given this->packet pointed by 'this->packet' to the network */ + +int +Video_Global::send_to_network (int timeToUse) +{ + int count = 0; + VideoMessage * msghd = (VideoMessage *) ( ( (char *)this->packet) - sizeof (VideoMessage)); + int sent = 0; + int packetSize = ntohl (this->packet->dataBytes); + + msghd->packetsn = htonl (this->packetsn ++); + msghd->packetSize = htonl (packetSize + sizeof (* this->packet)); + /* + fprintf (stderr, "VS to send pkt %d of size %d.\n", + ntohl (msghd->this->packetsn), ntohl (msghd->this->packetSize)); + */ + { + VideoMessage * msg = NULL; + int size = packetSize + sizeof (* this->packet); /* msghd->this->packetSize */ + int offset = 0; + int targetTime; + + if (size > this->msgsize) + { + + if (!timeToUse) + { + timeToUse = (this->msgsize + sizeof (*msg) + 28) * 2; + /* + set the max network as 500KB. + 28 - UDP header size + */ + /* + fprintf (stderr, "computed timeToUse %d. ", timeToUse); + */ + } + else + { + timeToUse = (timeToUse * 7) >> 3; + /* + fprintf (stderr, "preset timeToUse %d.", timeToUse); + */ + timeToUse /= (size + this->msgsize - 1) / this->msgsize; + timeToUse = min (timeToUse, (this->msgsize + sizeof (*msg) + 28) * 100); + /* limit min network bandwidth = 10K */ + } + + } + while (size > 0) + { + int segsize, sentsize; + int resent = 0; + + if (msg == NULL) { /* first message for current this->packet */ + count = 0; + msg = msghd; + targetTime = get_usec (); + } + else { +#if 0 + /* the select () is not precise enough for being used here*/ + int sleepTime; + targetTime += timeToUse; + sleepTime = get_duration (get_usec (), targetTime); + if (sleepTime >= 5000) { /* resolution of timer is 10,000 usec */ + usleep (sleepTime); /* not first message, wait for a while */ + } +#endif + /* + count ++; + if (! (count % 10)) usleep (10000); + */ + msg = (VideoMessage *) ( (char *)msg + this->msgsize); + memcpy ( (char *)msg, (char *)msghd, sizeof (* msg)); + } + msg->msgsn = htonl (this->msgsn++); + msg->msgOffset = htonl (offset); + msg->msgSize = htonl (min (size, this->msgsize)); + + segsize = min (size, this->msgsize)+sizeof (*msg); + if (this->conn_tag != 0) { /* this->packet stream */ + while ( (sentsize = write (this->videoSocket, (char *)msg, segsize)) == -1) { + if (errno == EINTR) + continue; + if (errno == ENOBUFS) { + if (resent) { + perror ("Warning, pkt discarded because"); + sent = -1; + break; + } + else { + resent = 1; + perror ("VS to sleep 5ms"); + usleep (5000); + continue; + } + } + if (errno != EPIPE) { + fprintf (stderr, "VS error on send this->packet %d of size %d ", + this->msgsn-1, min (size, this->msgsize)+sizeof (*msg)); + perror (""); + } + exit (errno != EPIPE); + } + } + else { + sentsize = wait_write_bytes (this->videoSocket, (char *)msg, segsize); + if (sentsize == -1) { + if (errno != EPIPE) { + fprintf (stderr, "VS error on send this->packet %d of size %d ", + this->msgsn-1, min (size, this->msgsize)+sizeof (*msg)); + perror (""); + } + exit (errno != EPIPE); + } + } + if (sentsize < segsize) { + SFprintf (stderr, "VS warning: message size %dB, sent only %dB\n", + segsize, sentsize); + } + if (sent == -1) + break; + /* + fprintf (stderr, "VS: message %d of size %d sent.\n", + this->msgsn-1, min (size, this->msgsize)+sizeof (*msg)); + */ + size -= this->msgsize; + offset += this->msgsize; + } + } + /* + fprintf (stderr, "sent = %d\n", sent); + */ + if (!sent) this->pkts_sent ++; + return sent; +} + +/* + * send a this->packet with given this->systemHeader (optional), gop (optional) and frame. + * + * sh - system header id, if -1, then no system header will be sent. + * otherwise, only when frame == 0, the given system header will be sent. + * gop - group of pictures, gop header will be sent when frame == 0 + * (first I frame ); + * frame - frame to be sent, offset internal to given gop. */ - TimerSpeed(); - // setsignal(SIGALRM, timerHandler); - timerOn = 1; - preTimerVal = get_usec(); + +/* returns: 0 - this->packet sent, -1 - this->packet not sent (failed) */ +int +Video_Global::SendPacket (int shtag, int gop, int frame, int timeToUse) +/* frame maybe out of range (PLAY, STEP), in this case, END_SEQ is sent + to force display of last frame in VD */ +{ + char * buf = ( (char *) this->packet) + sizeof (VideoPacket); + int f = this->gopTable[gop].previousFrames + frame; + int sh = this->gopTable[gop].systemHeader; + /* + SFprintf (stderr, "VS to send this->packet gop-%d, frame-%d.\n", gop, frame); + */ + + this->packet->currentUPF = ntohl (this->currentUPF); + + if (frame >= this->gopTable[gop].totalFrames) + { + this->packet->cmd = htonl (this->cmd); + this->packet->cmdsn = htonl (this->cmdsn); + this->packet->sh = htonl (sh); + this->packet->gop = htonl (gop); + this->packet->frame = htonl (this->numF); + this->packet->display = htonl (this->numF-1); + this->packet->future = htonl ( (unsigned)-1); + this->packet->past = htonl ( (unsigned)-1); + this->packet->dataBytes = htonl (4); + * (int*) ( (char*)this->packet + sizeof (*this->packet)) = htonl (SEQ_END_CODE); + + return send_to_network (timeToUse); + } + + if (frame) + shtag = 0; + else if (this->needHeader) + { + shtag = 1; + this->needHeader = 0; + } + + this->packet->cmd = htonl (this->cmd); + this->packet->cmdsn = htonl (this->cmdsn); + this->packet->sh = htonl (sh); + this->packet->gop = htonl (gop); + this->packet->frame = htonl (f); + if (this->frameTable[f].type == 'B') + { + int pre1 = -1, pre2 = -1, i = f; + while (i>0) + if (this->frameTable[--i].type != 'B') + { + pre1 = i; + break; + } + while (i>0) + if (this->frameTable[--i].type != 'B') + { + pre2 = i; + break; + } + if (pre2 == -1) + { + /* + fprintf (stderr, + "frame %d-%d (%d) is a B without past ref, no to be sent.\n", + gop, frame, f); + */ + return -1; + } + if (pre1 != this->lastRef[this->lastRefPtr] || + pre2 != this->lastRef[1 - this->lastRefPtr]) + { + /* + fprintf (stderr, + "send of B frame %d gaveup for past %d/future %d ref not sent.\n", + f, pre2, pre1); + */ + return -1; + } + this->packet->display = htonl (f); + this->packet->future = htonl (pre1); + this->packet->past = htonl (pre2); + } + else + { + int next = f; + int pre = f; + + while (next < this->numF && this->frameTable[++next].type == 'B'); + while (pre > 0 && this->frameTable[--pre].type == 'B'); + if (this->frameTable[f].type == 'P' && pre != this->lastRef[this->lastRefPtr]) + { + /* + fprintf (stderr, + "send of P frame %d gaveup for past ref %d not sent.\n", + f, pre); + fprintf (stderr, "ref0=%d, ref1=%d, ptr=%d.\n", + this->lastRef[0], this->lastRef[1], this->lastRefPtr); + */ + return -1; + } + this->packet->display = htonl (next); + this->packet->future = htonl ( (unsigned)-1); + this->packet->past = htonl (this->frameTable[f].type == 'P' ? pre : (unsigned)-1); + } + { + char * ptr = buf; + int size = 0, offset = 0, i; + if (shtag) /* send system header */ + { + size = this->systemHeader[sh].size; + FileRead (this->systemHeader[sh].offset, ptr, size); + ptr += size; + } + if (!frame) /* send gop header */ + { + size = this->gopTable[gop].headerSize; + FileRead (this->gopTable[gop].offset, ptr, size); + ptr += size; + } + size = this->frameTable[f].size; + for (i=this->gopTable[gop].previousFrames; i<f; i++) + offset += this->frameTable[i].size; + FileRead ( (this->gopTable[gop].firstIoffset + offset), ptr, size); + ptr += size; + this->packet->dataBytes = htonl (ptr - buf); + } + + { + int sent = send_to_network (timeToUse); + if (!sent) + { + /* + fprintf (stderr, "%c%d\n", this->frameTable[f].type, f); + fprintf (stderr, "%c frame %d sent.\n", this->frameTable[f].type, f); + */ + if (this->frameTable[f].type != 'B') + { + this->lastRefPtr = 1 - this->lastRefPtr; + this->lastRef[this->lastRefPtr] = f; + } + } + return sent; + } +} + + +int +Video_Global::CmdRead (char *buf, int psize) +{ + int res = wait_read_bytes (this->serviceSocket, + buf, + psize); + if (res == 0) return (1); + if (res == -1) { + fprintf (stderr, "VS error on read this->cmdSocket, size %d", psize); + perror (""); + return (-1); + } + return 0; +} + +int +Video_Global::CmdWrite (char *buf, int size) +{ + int res = wait_write_bytes (this->serviceSocket, buf, size); + if (res == -1) { + if (errno != EPIPE) perror ("VS writes to this->serviceSocket"); + return (-1); + } + return 0; +} + + +int +Video_Global::PLAYliveVideo (PLAYpara * para) +{ + int doscale; + int count; + int first_frame; + int frame = para->nextFrame; + int nfds = (this->serviceSocket > this->videoSocket ? this->serviceSocket : this->videoSocket) + 1; + struct fd_set read_mask; + struct timeval tval = {0, 0}; + double ratio; + int result; + + this->currentUPF = (int) (1000000.0 / this->fps); /* ignore para.usecPerFrame */ + if (this->frameRateLimit < this->fps) { + doscale = 1; + ratio = min (this->frameRateLimit, this->fps) / this->fps; + first_frame = frame; + count = 0; /* - fprintf(stderr, "VS: timer started at %d upf.\n", VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF); + fprintf (stderr, "doscale %d, this->frameRateLimit %5.2f, this->fps %5.2f, ratio %5.2f\n", + doscale, this->frameRateLimit, this->fps, ratio); */ + } + else doscale = 0; + StartPlayLiveVideo (); + + for (;;) { + + if (doscale) { + for (;;) { + if ( (int) ( (frame - first_frame) * ratio + 0.5) < count) frame ++; + else break; + } + count ++; + } + SendPicture (&frame); + frame ++; + + FD_ZERO (&read_mask); + FD_SET (this->serviceSocket, &read_mask); + FD_SET (this->videoSocket, &read_mask); +#ifdef _HPUX_SOURCE + if (select (nfds, (int *)&read_mask, NULL, NULL, &tval) == -1) +#else + if (select (nfds, &read_mask, NULL, NULL, &tval) == -1) +#endif + { + if (errno == EINTR) + continue; + perror ("Error - VS select between service and video sockets"); + StopPlayLiveVideo (); + exit (1); + + } + if (FD_ISSET (this->serviceSocket, &read_mask)) /* stop */ + { + unsigned char tmp; + result = CmdRead ( (char *)&tmp, 1); + if (result != 0) + return result; + if (tmp == CmdCLOSE) { + StopPlayLiveVideo (); + exit (0); + } + else if (tmp == CmdSTOP) { + this->cmd = tmp; + /* + fprintf (stderr, "VS: this->CmdSTOP. . .\n"); + */ + result = CmdRead ( (char *)&this->cmdsn, sizeof (int)); + if (result != 0) + return result; +#ifdef NeedByteOrderConversion + this->cmdsn = ntohl (this->cmdsn); +#endif + StopPlayLiveVideo (); + break; + } + else if (tmp == CmdSPEED) + { + SPEEDpara speed_para; + /* + fprintf (stderr, "VS: this->CmdSPEED. . .\n"); + */ + result = CmdRead ( (char *)&speed_para, sizeof (speed_para)); + if (result != 0) + return result; + /* ignore this thing for live video */ + } + else + { + fprintf (stderr, "VS error (live): this->cmd=%d while expect STOP/SPEED.\n", tmp); + this->normalExit = 0; + StopPlayLiveVideo (); + exit (1); + } + } + if (FD_ISSET (this->videoSocket, &read_mask)) /* feedback, only for frame rate + adjustment */ + { + VideoFeedBackPara fb_para; + if (FBread ( (char *)&fb_para, sizeof (fb_para)) == -1 || + ntohl (fb_para.cmdsn) != this->cmdsn) { + /* + SFprintf (stderr, "VS warning: a FB this->packet discarded.\n"); + */ + return 0; + } +#ifdef NeedByteOrderConversion + fb_para.this->frameRateLimit1000 = ntohl (fb_para.this->frameRateLimit1000); +#endif + this->frameRateLimit = fb_para.frameRateLimit1000 / 1000.0; + if (this->frameRateLimit < this->fps) { + doscale = 1; + ratio = min (this->frameRateLimit, this->fps) / this->fps; + first_frame = frame; + count = 0; + /* + fprintf (stderr, "doscale %d, this->frameRateLimit %5.2f, this->fps %5.2f, ratio %5.2f\n", + doscale, this->frameRateLimit, this->fps, ratio); + */ + } + else doscale = 0; + } + } + return 0; } void -Video_Timer_Global::StopTimer (void) +Video_Global::ComputeFirstSendPattern (float limit) { - struct itimerval val; - // @@Naga I have to incorporate this logic into the changed code - // setsignal(SIGALRM, SIG_IGN); - val.it_interval.tv_sec = val.it_value.tv_sec = 0; - val.it_interval.tv_usec = val.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &val, NULL); - timerOn = 0; - /* - fprintf(stderr, "VS: timer stopped.\n"); - */ + char * buf = this->firstSendPattern; + int len = this->firstPatternSize; + char * pat = (char *)malloc (len); + int f; + + if (pat == NULL) { + fprintf (stderr, "VS error on allocating %d bytes for computing first SP", len); + perror (""); + exit (1); + } + for (f = 0; f < len; f ++) { + pat[f] = this->frameTable[f].type; + } + memset (buf, 0, len); + + if (limit <= 0) + limit = 1.0; + + f = (int) ( (double)len * + ( (double)limit / (1000000.0 / (double)this->currentUPF)) + 0.5); + /* rounded to integer, instead of truncated */ + if (f >= len) + f = len; + else if (f <= 1) + f = 1; + + ComputeSendPattern (pat, buf, len, f); + + /* + f = len - f; + fprintf (stderr, "this->Firstthis->Sendthis->Pattern (%d frames dropped): ", f); + { + int i; + for (i = 0; i < len; i ++) + fputc (buf[i] ? pat[i] : '-', stderr); + } + fputc ('\n', stderr); + */ + free (pat); +} + +int +Video_Global::FrameToGroup (int * frame) +{ + int f = * frame; + int i = 0; + while (i < this->numG && this->gopTable[i].previousFrames <= f) i++; + i --; + * frame = f - this->gopTable[i].previousFrames; + return i; } +int +Video_Global::SendReferences (int group, int frame) +{ + unsigned char orgcmd; + int i, base; + int pregroup; + int result; + + if (group < 0 || group >= this->numG) return 0; + if (frame <= 0 || frame >= this->gopTable[group].totalFrames) return 0; + + orgcmd = this->cmd; + this->cmd = CmdREF; + + if (group > 0) { + pregroup = 1; + base = this->gopTable[group].previousFrames; + for (i = 0; i <= frame; i ++) { + if (this->frameTable[i + base].type == 'P') { + pregroup = 0; + break; + } + } + } + else pregroup = 0; + + if (pregroup) { /* reference frame can be in previous group */ + pregroup = group -1; + base = this->gopTable[pregroup].previousFrames; + for (i = 0; i < this->gopTable[pregroup].totalFrames; i ++) { + if (this->frameTable[i + base].type != 'B') { + /* + SFprintf (stderr, "REF group%d, frame%d\n", pregroup, i); + */ + result = SendPacket (i == 0, pregroup, i, 0); + if (result != 0) + return result; + } + } + } + + base = this->gopTable[group].previousFrames; + for (i = 0; i < frame; i ++) { + if (this->frameTable[i + base].type != 'B') { + /* + SFprintf (stderr, "REF group%d, frame%d\n", group, i); + */ + SendPacket (i == 0, group, i, 0); + } + } + this->cmd = orgcmd; +} + + void -Video_Timer_Global::TimerSpeed (void) +Video_Global::GetFeedBack () { - struct itimerval val; - int usec = VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF; - if (Mpeg_Global::drift_ppm) { - /* - int drift = (double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0; - SFprintf(stderr, "Mpeg_Global::drift_ppm %d, usec %d, drift %d, new usec %d\n", - Mpeg_Global::drift_ppm, usec, drift, usec - drift); - */ - usec -= (int)((double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0); - } - if (timerAdjust > 1) - usec = (int)(((double)usec * (double)(SPEEDUP_INV_SCALE - 1)) / - (double)SPEEDUP_INV_SCALE); - val.it_interval.tv_sec = val.it_value.tv_sec = usec / 1000000; - val.it_interval.tv_usec = val.it_value.tv_usec = usec % 1000000; - setitimer(ITIMER_REAL, &val, NULL); + VideoFeedBackPara para; + struct itimerval val; + int timerUsec; + + if (FBread ( (char *)¶, sizeof (para)) == -1 || + ntohl (para.cmdsn) != this->cmdsn) { /* - SFprintf(stderr, - "VS TimerSpeed() at %s speed, timerAdjust %d VIDEO_SINGLETON::instance ()->addedSignals %d.\n", - (timerAdjust > 1) ? "higher" : "normal", timerAdjust, VIDEO_SINGLETON::instance ()->addedSignals); + SFprintf (stderr, "VS warning: a FB this->packet discarded.\n"); */ + return; + } +#ifdef NeedByteOrderConversion + para.this->needHeader = ntohl (para.this->needHeader); + para.addUsecPerFrame = ntohl (para.addUsecPerFrame); + para.addFrames = ntohl (para.addFrames); + para.this->sendthis->PatternGops = ntohl (para.this->sendthis->PatternGops); + para.this->frameRateLimit1000 = ntohl (para.this->frameRateLimit1000); +#endif + this->frameRateLimit = para.frameRateLimit1000 / 1000.0; + this->sendPatternGops = para.sendPatternGops; + + if (!Video_Timer_Global::timerOn) return; + + this->needHeader = para.needHeader; + memcpy (this->sendPattern, para.sendPattern, PATTERN_SIZE); + if (para.addFrames <= 0 || Video_Timer_Global::timerAdjust < MAX_TIMER_ADJUST) + { + Video_Timer_Global::timerAdjust += para.addFrames * SPEEDUP_INV_SCALE; + Video_Timer_Global::TimerSpeed (); + } + else /* drastic compensation for big gap */ + this->addedSignals += para.addFrames; + if (para.addUsecPerFrame) { + this->addedUPF += para.addUsecPerFrame; + Video_Timer_Global::TimerSpeed (); + } + /* + SFprintf (stderr, "VS fb: addf %d, addupf %d\n", + para.addFrames, para.addUsecPerFrame); + */ +} + +int +Video_Global::SendPicture (int * frame) +{ + int size; + char * buf = ( (char *) this->packet) + sizeof (VideoPacket); + /* + SFprintf (stderr, "VS to send picture %d.\n", *frame); + */ + + size = ReadLiveVideoPicture (frame, buf, this->packetBufSize); + + this->packet->currentUPF = ntohl (this->currentUPF); + this->packet->cmd = htonl (this->cmd); + this->packet->cmdsn = htonl (this->cmdsn); + this->packet->sh = this->packet->gop = this->packet->frame = this->packet->display = htonl (*frame); + this->packet->future = htonl ( (unsigned)-1); + this->packet->past = htonl ( (unsigned)-1); + this->packet->dataBytes = htonl (size); + + return send_to_network (this->currentUPF); +} + +int +Video_Global::ReadInfoFromFile (void) +{ + int fd = -1, i; + int fnlen = strlen (this->videoFile); + + strcpy (&this->videoFile[fnlen], ".Info"); + fd = open (this->videoFile, O_RDONLY); + if (fd == -1) + { + fprintf (stderr, "Reminder: VS fails to open %s for read, ", this->videoFile); + perror ("try create one"); + goto fail_ReadInfoFromFile; + } + read_int (fd, &i); + if (i != this->fileSize) + { + fprintf (stderr, "Warning: this->fileSize in Info: %d not the same as actual %d.\n", + i, this->fileSize); + goto fail_ReadInfoFromFile; + } + + read_int (fd, &this->maxS); + read_int (fd, &this->maxG); + read_int (fd, &this->maxI); + read_int (fd, &this->maxP); + read_int (fd, &this->maxB); + read_int (fd, &this->minS); + read_int (fd, &this->minG); + read_int (fd, &this->minI); + read_int (fd, &this->minP); + read_int (fd, &this->minB); + read_int (fd, &this->numS); + read_int (fd, &this->numG); + read_int (fd, &this->numF); + read_int (fd, &this->numI); + read_int (fd, &this->numP); + read_int (fd, &this->numB); + read_int (fd, &this->averageFrameSize); + read_int (fd, &this->horizontalSize); + read_int (fd, &this->verticalSize); + read_int (fd, &this->pelAspectRatio); + read_int (fd, &this->pictureRate); + read_int (fd, &this->vbvBufferSize); + read_int (fd, &this->patternSize); + + memset (this->pattern, 0, PATTERN_SIZE); + read_bytes (fd, this->pattern, this->patternSize); +#ifdef STAT + this->framesSent = (char *)malloc ( (this->numF + 7)>>3); + if (this->framesSent == NULL) + { + fprintf (stderr, "Error: VS fails to alloc mem for this->framesSent for %d frames", this->numF); + perror (""); + exit (1); + } +#endif + this->systemHeader = (struct Video_Global::SystemHeader *)malloc (sizeof (struct Video_Global::SystemHeader) * this->numS); + if (this->systemHeader == NULL) + { + perror ("Error: VS error on malloc this->SystemHeader"); + exit (1); + } + this->gopTable = (struct Video_Global::GopTable *)malloc (sizeof (struct Video_Global::GopTable) * this->numG); + if (this->gopTable == NULL) + { + perror ("Error: VS error on malloc GopHeader"); + exit (1); + } + this->frameTable = (struct Video_Global::FrameTable *)malloc (sizeof (Video_Global::FrameTable) * this->numF); + if (this->frameTable == NULL) + { + perror ("Error: VS error on malloc this->frameTable"); + exit (1); + } + this->packetBufSize = this->maxS + this->maxG + max (this->maxI, max (this->maxP, this->maxB)); + this->packet = (VideoPacket *)malloc (sizeof (VideoMessage) + sizeof (VideoPacket) + + this->packetBufSize); + if (this->packet == NULL) + { + perror ("Error: VS error on malloc this->packet buffer"); + exit (1); + } + this->packet = (VideoPacket *) ( (char *)this->packet + sizeof (VideoMessage)); + + for (i = 0; i < this->numS; i ++) + { + read_int (fd, (int *)&this->systemHeader[i].offset); + read_int (fd, &this->systemHeader[i].size); + } + for (i = 0; i < this->numG; i ++) + { + read_int (fd, &this->gopTable[i].systemHeader); + read_int (fd, (int *)&this->gopTable[i].offset); + read_int (fd, &this->gopTable[i].headerSize); + read_int (fd, &this->gopTable[i].size); + read_int (fd, &this->gopTable[i].totalFrames); + read_int (fd, &this->gopTable[i].previousFrames); + read_int (fd, (int *)&this->gopTable[i].firstIoffset); + } + for (i = 0; i < this->numF; i ++) + { + read_byte (fd, &this->frameTable[i].type); + read_short (fd, (short *)&this->frameTable[i].size); + } + + close (fd); + /* + fprintf (stderr, "Read Info from %s\n", this->videoFile); + */ + this->videoFile[fnlen] = 0; + return 0; + fail_ReadInfoFromFile: + if (fd >= 0) + close (fd); + this->videoFile[fnlen] = 0; + /* + fprintf (stderr, "To scan Info from %s\n", this->videoFile); + */ + return -1; } void -Video_Timer_Global::TimerProcessing (void) +Video_Global::WriteInfoToFile (void) { -/* - fprintf(stderr, "VS: timerHandler...\n"); -*/ - if (!timerOn) { - return; + int fd = -1, i; + int fnlen = strlen (this->videoFile); + + strcpy (&this->videoFile[fnlen], ".Info"); + fd = open (this->videoFile, O_WRONLY | O_CREAT, 0444); + if (fd == -1) + { + fprintf (stderr, "VS fails to open %s for write", this->videoFile); + perror (""); + goto fail_WriteInfoToFile; + } + write_int (fd, this->fileSize); + write_int (fd, this->maxS); + write_int (fd, this->maxG); + write_int (fd, this->maxI); + write_int (fd, this->maxP); + write_int (fd, this->maxB); + write_int (fd, this->minS); + write_int (fd, this->minG); + write_int (fd, this->minI); + write_int (fd, this->minP); + write_int (fd, this->minB); + write_int (fd, this->numS); + write_int (fd, this->numG); + write_int (fd, this->numF); + write_int (fd, this->numI); + write_int (fd, this->numP); + write_int (fd, this->numB); + write_int (fd, this->averageFrameSize); + write_int (fd, this->horizontalSize); + write_int (fd, this->verticalSize); + write_int (fd, this->pelAspectRatio); + write_int (fd, this->pictureRate); + write_int (fd, this->vbvBufferSize); + write_int (fd, this->patternSize); + + write_bytes (fd, this->pattern, this->patternSize); + + for (i = 0; i < this->numS; i ++) + { + write_int (fd, this->systemHeader[i].offset); + write_int (fd, this->systemHeader[i].size); + } + for (i = 0; i < this->numG; i ++) + { + write_int (fd, this->gopTable[i].systemHeader); + write_int (fd, this->gopTable[i].offset); + write_int (fd, this->gopTable[i].headerSize); + write_int (fd, this->gopTable[i].size); + write_int (fd, this->gopTable[i].totalFrames); + write_int (fd, this->gopTable[i].previousFrames); + write_int (fd, this->gopTable[i].firstIoffset); + } + for (i = 0; i < this->numF; i ++) + { + write_byte (fd, this->frameTable[i].type); + write_short (fd, this->frameTable[i].size); + } + + close (fd); + this->videoFile[fnlen] = 0; + return; + fail_WriteInfoToFile: + if (fd >= 0) + close (fd); + this->videoFile[fnlen] = 0; + return; +} + +int +Video_Global::init_MPEG1_video_file (void) +{ + unsigned char nb; + int state = 0; + unsigned long fileptr = 0; + unsigned long i, j, k; + int shptr, gopptr, ftptr; + int inpic = 0; + unsigned long picptr = 0; + int pictype = 0; + int first = 0; + int failureType = 0; + + this->fp = fopen (this->videoFile, "r"); + if (this->fp == NULL) + { + fprintf (stderr, "error on opening video file %s", this->videoFile); + perror (""); + return 2; + } + if (fseek (this->fp, 0, 2) == -1) + { + fprintf (stderr, "File %s not seekable", this->videoFile); + perror (""); + return 3; + } + this->fileSize = ftell (this->fp); + + fseek (this->fp, 0, 0); + + if (ReadInfoFromFile ()) + { + for (;;) + { + nextByte; + if (state >= 0 && nb == 0x00) + state ++; + else if (state >= 2 && nb == 0x01) + state = -1; + else if (state == -1) + { + if (!first) first ++; + else if (first == 1) first ++; + + switch (nb) + { + case 0xb7: /* seq_end_code */ + goto exit_phase1; + break; + case 0xb3: /* seq_start_code */ + if (first == 1) first = 3; + if (first != 3) + { + fprintf (stderr, "VS error: given file is not in MPEG format.\n"); + return 4; + } + this->numS ++; + break; + case 0xb8: /* gop_start_code */ + this->numG ++; + break; + case 0x00: /* picture_start_code */ + nextByte; + nextByte; + nb &= 0x38; + if (nb == 0x08) + { + this->numI ++; + if (this->numG == 2) + this->pattern[this->patternSize++] = 'I'; + } + else if (nb == 0x10) + { + this->numP ++; + if (this->numG == 2) + this->pattern[this->patternSize++] = 'P'; + } + else if (nb == 0x18) + { + this->numB ++; + if (this->numG == 2) + this->pattern[this->patternSize++] = 'B'; + } + /* + else + fprintf (stderr, "VS error: unkonw picture type %d\n", nb); + */ + break; + default: + break; + } + state = 0; + } + else + state = 0; } - if (timerAdjust < 0) + exit_phase1: + + if (first != 3) { - timerAdjust += SPEEDUP_INV_SCALE; - return; + fprintf (stderr, "VS error: given file \"%s\" is not of MPEG format.\n", this->videoFile); + return 4; } - if (timerAdjust >0) + + this->pattern[this->patternSize] = 0; + memset (this->sendPattern, 1, PATTERN_SIZE); + + this->numF = this->numI + this->numP + this->numB; + this->averageFrameSize = fileptr / (unsigned)this->numF; + /* + fprintf (stderr, "Pass one finished, total bytes read: %u, average frame size %d\n", + fileptr, this->averageFrameSize); + fprintf (stderr, "this->numS-%d, this->numG-%d, this->numF-%d, this->numI-%d, this->numP-%d, this->numB-%d\n", + this->numS, this->numG, this->numI, this->numI, this->numP, this->numB); + fprintf (stderr, "this->Pattern detected: %s\n", this->pattern); + */ + if (this->numF > MAX_FRAMES) { - if ((--timerAdjust) == 0) - TimerSpeed(); + fprintf (stderr, "VS error: this->Number of frames (%d) is bigger than MAX_FRAMES (%d).\n\ + you need to update the constant definition in common.h and recompile.\n", + this->numF, MAX_FRAMES); + return 5; } - if (VIDEO_SINGLETON::instance ()->cmd == CmdPLAY) + +#ifdef STAT + this->framesSent = (char *)malloc ( (this->numF + 7)>>3); + if (this->framesSent == NULL) + { + fprintf (stderr, "VS fails to alloc mem for this->framesSent for %d frames", this->numF); + perror (""); + return 6; + } +#endif + + this->systemHeader = (struct Video_Global::SystemHeader *)malloc (sizeof (struct Video_Global::SystemHeader) * this->numS); + if (this->systemHeader == NULL) { - if (timerGroup == VIDEO_SINGLETON::instance ()->numG - 1 && timerFrame >= VIDEO_SINGLETON::instance ()->gopTable[timerGroup].totalFrames - 1) + perror ("VS error on malloc this->SystemHeader"); + return 7; + } + this->gopTable = (struct Video_Global::GopTable *)malloc (sizeof (struct Video_Global::GopTable) * this->numG); + if (this->gopTable == NULL) + { + perror ("VS error on malloc GopHeader"); + return 8; + } + this->frameTable = (struct Video_Global::FrameTable *)malloc (sizeof (Video_Global::FrameTable) * this->numF); + if (this->frameTable == NULL) + { + perror ("VS error on malloc this->frameTable"); + return 9; + } + + rewind (this->fp); + fileptr = 0; + state = 0; + inpic = 0; + shptr = -1; + gopptr = -1; + ftptr = 0; + + for (;;) + { + nextByte; + if (state >= 0 && nb == 0x00) + state ++; + else if (state >= 2 && nb == 0x01) + state = -1; + else if (state == -1) + { + switch (nb) + { + case 0xb7: /* seq_end_code */ + if (gopptr >= 0 && this->gopTable[gopptr].size == 0) + this->gopTable[gopptr].size = fileptr - this->gopTable[gopptr].offset - 4; + computePicSize; + goto exit_phase2; + break; + case 0xb3: /* seq_start_code */ + if (gopptr >= 0 && this->gopTable[gopptr].size == 0) + this->gopTable[gopptr].size = fileptr - this->gopTable[gopptr].offset - 4; + computePicSize; + shptr ++; + this->systemHeader[shptr].offset = fileptr - 4; + this->systemHeader[shptr].size = 0; + break; + case 0xb8: /* gop_start_code */ + if (this->systemHeader[shptr].size == 0) + this->systemHeader[shptr].size =fileptr - this->systemHeader[shptr].offset - 4; + if (gopptr >= 0 && this->gopTable[gopptr].size == 0) + this->gopTable[gopptr].size = fileptr - this->gopTable[gopptr].offset - 4; + computePicSize; + gopptr ++; + this->gopTable[gopptr].systemHeader = shptr; + this->gopTable[gopptr].offset = fileptr - 4; + this->gopTable[gopptr].headerSize = 0; + this->gopTable[gopptr].size = 0; + this->gopTable[gopptr].totalFrames = 0; + this->gopTable[gopptr].previousFrames = gopptr ? + (this->gopTable[gopptr - 1].totalFrames + this->gopTable[gopptr - 1].previousFrames) : 0; + + break; + case 0x00: /* picture_start_code */ + if (this->gopTable[gopptr].headerSize == 0) + { + this->gopTable[gopptr].headerSize = fileptr - this->gopTable[gopptr].offset - 4; + this->gopTable[gopptr].firstIoffset = fileptr - 4; + } + this->gopTable[gopptr].totalFrames ++; + computePicSize; + picptr = fileptr - 4; + nextByte; + nextByte; + nb &= 0x38; + if (nb == 0x08) + { + pictype = 'I'; + inpic = 1; + } + else if (nb == 0x10) + { + pictype = 'P'; + inpic = 1; + } + else if (nb == 0x18) + { + pictype = 'B'; + inpic = 1; + } + break; + default: + + break; + } + state = 0; + } + else + state = 0; + } + + exit_phase2: + for (shptr = 0; shptr<this->numS; shptr++) + { + this->maxS = max (this->maxS, this->systemHeader[shptr].size); + this->minS = min (this->minS, this->systemHeader[shptr].size); + } + for (gopptr = 0; gopptr<this->numG; gopptr++) + { + this->maxG = max (this->maxG, this->gopTable[gopptr].headerSize); + this->minG = min (this->minG, this->gopTable[gopptr].headerSize); + } + this->packetBufSize = this->maxS + this->maxG + max (this->maxI, max (this->maxP, this->maxB)); + this->packet = (VideoPacket *)malloc (sizeof (VideoMessage) + sizeof (VideoPacket) + + this->packetBufSize); + if (this->packet == NULL) + { + perror ("VS error on malloc this->packet buffer"); + return 10; + } + this->packet = (VideoPacket *) ( (char *)this->packet + sizeof (VideoMessage)); + /* + fprintf (stderr, "Pass 2 finished.\n"); + fprintf (stderr, "this->maxS-%d, this->maxG-%d, this->maxI-%d, this->maxP-%d, this->maxB-%d.\n", this->maxS, this->maxG, this->maxI, this->maxP, this->maxB); + fprintf (stderr, "this->minS-%d, this->minG-%d, this->minI-%d, this->minP-%d, this->minB-%d.\n", this->minS, this->minG, this->minI, this->minP, this->minB); + */ + /* + { + int i; + + fprintf (stderr, "id: offset size -- system header table:\n"); + for (i=0; i<this->numS; i++) + fprintf (stderr, "%-3d %-9u %d\n", i, this->systemHeader[i].offset, this->systemHeader[i].size); + fprintf (stderr, + "id: header offset hdsize totSize frames preframs Ioffset Isize -- GOP\n"); + for (i=0; i<this->numG; i++) + { + fprintf (stderr, "%-4d %-8d %-8u %-8d %-8d %-8d %-8d %-8u %d\n", + i, + this->gopTable[i].this->systemHeader, + this->gopTable[i].offset, + this->gopTable[i].headerSize, + this->gopTable[i].size, + this->gopTable[i].totalFrames, + this->gopTable[i].previousFrames, + this->gopTable[i].firstIoffset, + this->frameTable[this->gopTable[i].previousFrames].size + ); + } + + fprintf (stderr, "\nframe information:"); + for (i=0; i<this->numF; i++) + fprintf (stderr, "%c%c%-8d", (i%10 ? '\0' : '\n'), this->frameTable[i].type, this->frameTable[i].size); + fprintf (stderr, "\n"); + + } + */ + fseek (this->fp, this->systemHeader[0].offset+4, 0); + nextByte; + this->horizontalSize = ( (int)nb <<4) & 0xff0; + nextByte; + this->horizontalSize |= (nb >>4) & 0x0f; + this->verticalSize = ( (int)nb <<8) & 0xf00; + nextByte; + this->verticalSize |= (int)nb & 0xff; + nextByte; + this->pelAspectRatio = ( (int)nb >> 4) & 0x0f; + this->pictureRate = (int)nb & 0x0f; + nextByte; + nextByte; + nextByte; + this->vbvBufferSize = ( (int)nb << 5) & 0x3e0; + nextByte; + this->vbvBufferSize |= ( (int)nb >>3) & 0x1f; + /* + fprintf (stderr, "SysHeader info: hsize-%d, vsize-%d, pelAspect-%d, rate-%d, vbv-%d.\n", + this->horizontalSize, this->verticalSize, this->pelAspectRatio, this->pictureRate, this->vbvBufferSize); + */ + WriteInfoToFile (); + } +#if 0 + { + int i, j = 20; + + for (i = this->numG - 1;; i --) { + if (this->gopTable[i].offset < 4235260) { + fprintf (stderr, "group %d: offset %ld\n", i, this->gopTable[i].offset); + if (j -- == 0) break; + } + } + /* + for (i = 0; i < this->numG; i ++) { + if (this->gopTable[i].previousFrames > 1800) { + fprintf (stderr, "group %d: offset %ld pre-frames %d\n", + i, this->gopTable[i].offset, this->gopTable[i].previousFrames); + break; + } + } + */ + } +#endif + { + this->firstPatternSize = this->gopTable[0].totalFrames; + this->firstSendPattern = (char *)malloc (this->firstPatternSize); + if (this->firstSendPattern == NULL) + { + fprintf (stderr, "VS failed to allocate this->firstthis->Sendthis->Pattern for %d frames", + this->firstPatternSize); + perror (""); + return 11; + } + } + this->firstGopFrames = this->gopTable[0].totalFrames; + return 0; +} +int +Video_Global::play_send (int debug) +{ + + // ACE_DEBUG ( (LM_DEBUG,"play_send: sending the frame \n")); + int curGroup = Video_Timer_Global::timerGroup; + int curFrame = Video_Timer_Global::timerFrame; + int curHeader = Video_Timer_Global::timerHeader; + char * sp; + + if (this->preGroup != curGroup || + curFrame != this->preFrame) + { + int sendStatus = -1; + int frameStep = 1; + if (debug) + cerr << " curgroup = " << curGroup << endl ; + if (curGroup == 0) { - timerFrame ++; /* force sending of END_SEQ when PLAY VIDEO_SINGLETON::instance ()->cmd */ - StopTimer(); - return; + + int i = curFrame + 1; + while (i < this->firstPatternSize && + !this->firstSendPattern[i]) + { + frameStep ++; + i++; + } } - else + else /* (curGroup > 0) */ { - timerFrame ++; - if (timerFrame >= VIDEO_SINGLETON::instance ()->gopTable[timerGroup].totalFrames) + int i = curFrame + 1; + sp = this->sendPattern + ( (curGroup - 1) % this->sendPatternGops) * this->patternSize; + while (i < this->patternSize && !sp[i]) { - timerGroup ++; - timerFrame = 0; - timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; + frameStep ++; + i++; } } - } - else { - if (VIDEO_SINGLETON::instance ()->cmd == CmdFF) { - if (timerGroup == VIDEO_SINGLETON::instance ()->numG - 1) { - StopTimer(); - return; + if (curGroup == 0) + { + if (debug) + cerr << "first : " << + this->firstSendPattern[curFrame] << endl; + if (this->firstSendPattern[curFrame]) + sendStatus = 0; + else /* (!this->firstthis->Sendthis->Pattern[curFrame]) */ + { + int i = curFrame - 1; + while (i > 0 && !this->firstSendPattern[i]) + i--; + if (i > this->preFrame) + /* the frame (curGroup, i) hasn't been sent yet */ + { + sendStatus = 0; + curFrame = i; + } + else + sendStatus = -1; + if (debug) + cerr << "SendStatus = " << sendStatus << endl; } - timerGroup ++; - timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; } - else { - if (timerGroup == 0) { - StopTimer(); - return; + else if (sp[curFrame]) /* curGroup > 0 */ + sendStatus = 0; + else /* (!sp[curFrame]) */ + { + int i = curFrame - 1; + while (i > 0 && !sp[i]) + i--; + if (curGroup == this->preGroup && i > this->preFrame) + /* the frame (curGroup, i) hasn't been sent yet */ + { + sendStatus = 0; + curFrame = i; + } + else + sendStatus = -1; + } + if (!sendStatus) + { + // Send the current video frame, calls send_to_network which + // fragments and sends via blocking write . + sendStatus = this->SendPacket (this->preHeader != curHeader, + curGroup, curFrame, + (this->currentUPF + this->addedUPF) * frameStep); + if (!sendStatus) + { + this->preHeader = curHeader; + this->preGroup = curGroup; + this->preFrame = curFrame; +#ifdef STAT + if (this->play_para.collectStat) + { + int f = this->gopTable[curGroup].previousFrames + curFrame; + this->framesSent[f>>3] |= (1 << (f % 8)); + } +#endif } - timerGroup --; - timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; } } + return 0; +} +int +Video_Global::fast_play_send (void) +{ + if (this->fast_preGroup != Video_Timer_Global::timerGroup) + { + this->SendPacket (this->fast_preHeader != Video_Timer_Global::timerHeader, Video_Timer_Global::timerGroup, 0, + this->fast_para.usecPerFrame * this->patternSize >> 2); + this->fast_preHeader = Video_Timer_Global::timerHeader; + this->fast_preGroup = Video_Timer_Global::timerGroup; + } + return 0; } -void -Video_Timer_Global::timerHandler (int sig) +int +Video_Global::position (void) +{ + int result; + POSITIONpara pos_para; + /* + fprintf (stderr, "POSITION . . .\n"); + */ + result = CmdRead ( (char *)&pos_para, sizeof (pos_para)); + if (result != 0) + return result; + + if (this->live_source) return 0; + +#ifdef NeedByteOrderConversion + pos_para.nextGroup = ntohl (pos_para.nextGroup); + pos_para.sn = ntohl (pos_para.sn); +#endif + + CheckGroupRange (pos_para.nextGroup); + this->cmdsn = pos_para.sn; + result = SendPacket (this->numS>1 || pos_para.nextGroup == 0, pos_para.nextGroup, 0, 0); + return result; +} + +int +Video_Global::step_video () +{ + int group; + STEPpara step_para; + int tag = 0; + int result; + + result = CmdRead ( (char *)&step_para, sizeof (step_para)); + if (result != 0) + return result; +#ifdef NeedByteOrderConversion + step_para.sn = ntohl (step_para.sn); + step_para.this->nextFrame = ntohl (step_para.this->nextFrame); +#endif + + this->cmdsn = step_para.sn; + + if (!this->live_source) { + if (step_para.nextFrame >= this->numF) /* send SEQ_END */ + { + tag = 1; + step_para.nextFrame --; + } + /* + fprintf (stderr, "STEP . . .frame-%d\n", step_para.this->nextFrame); + */ + CheckFrameRange (step_para.nextFrame); + group = FrameToGroup (&step_para.nextFrame); + if (this->precmd != CmdSTEP && !tag ) { + result = SendReferences (group, step_para.nextFrame); + if (result < 0 ) + return result; + } + } + if (this->live_source) StartPlayLiveVideo (); + + if (this->live_source) { + SendPicture (&step_para.nextFrame); + } + else if (this->video_format == VIDEO_MPEG1) { + SendPacket (this->numS>1, group, tag ? this->numF : step_para.nextFrame, 0); + } + else { + fprintf (stderr, "VS: wierd1\n"); + } + + if (this->live_source) StopPlayLiveVideo (); + return 0; +} + +int +Video_Global::fast_forward (void) +{ + return this->init_fast_play (); +} + +int +Video_Global::fast_backward (void) +{ + return this->init_fast_play (); +} + +int +Video_Global::stat_stream (void) +{ + int i, j = 0; + for (i = 0; i < this->numF; i++) + { + short size = htons (this->frameTable[i].size); + char type = this->frameTable[i].type; + if (i == this->gopTable[j].previousFrames) + { + type = tolower (type); + j ++; + } + CmdWrite ( (char *)&type, 1); + CmdWrite ( (char *)&size, 2); + } + return 0; +} + +int +Video_Global::stat_sent (void) +{ +#ifdef STAT + CmdWrite ( (char *)this->framesSent, (this->numF + 7) / 8); +#else + int i; + char zeroByte = 0; + for (i = 0; i < (this->numF + 7) / 8; i++) + CmdWrite ( (char *)&zeroByte, 1); +#endif + return 0; +} + +int +Video_Global::init_play (void) +{ + int result; + + ACE_DEBUG ( (LM_DEBUG, + " (%P|%t) this->play ()")); + + // this gets the parameters for the play command + result = this->CmdRead ( (char *)&this->play_para, sizeof (this->play_para)); + if (result != 0) + return result; +#ifdef NeedByteOrderConversion + this->play_para.sn = ntohl (this->play_para.sn); + this->play_para.this->nextFrame = ntohl (this->play_para.this->nextFrame); + this->play_para.usecPerFrame = ntohl (this->play_para.usecPerFrame); + this->play_para.framesPerSecond = ntohl (this->play_para.framesPerSecond); + this->play_para.this->frameRateLimit1000 = ntohl (this->play_para.this->frameRateLimit1000); + this->play_para.collectStat = ntohl (this->play_para.collectStat); + this->play_para.this->sendPatternGops = ntohl (this->play_para.this->sendPatternGops); + this->play_para.this->VStimeAdvance = ntohl (this->play_para.this->VStimeAdvance); +#endif + + this->frameRateLimit = this->play_para.frameRateLimit1000 / 1000.0; + this->cmdsn = this->play_para.sn; + this->currentUPF = this->play_para.usecPerFrame; + this->VStimeAdvance = this->play_para.VStimeAdvance; + + { + int ts = htonl (get_usec ()); + this->CmdWrite ( (char *)&ts, sizeof (int)); + } + + if (this->live_source || this->video_format != VIDEO_MPEG1) { + if (this->live_source) + this->PLAYliveVideo (&this->play_para); + return 0; + } + + fprintf (stderr, "this->VStimeAdvance from client: %d\n", this->VStimeAdvance); + + this->sendPatternGops = this->play_para.sendPatternGops; + ComputeFirstSendPattern (this->frameRateLimit); +#ifdef STAT + if (this->play_para.collectStat) + memset (this->framesSent, 0, (this->numF + 7)>>3); +#endif + CheckFrameRange (this->play_para.nextFrame); + Video_Timer_Global::timerFrame = this->play_para.nextFrame; + Video_Timer_Global::timerGroup = FrameToGroup (&Video_Timer_Global::timerFrame); + Video_Timer_Global::timerHeader = this->gopTable[Video_Timer_Global::timerGroup].systemHeader; + memcpy (this->sendPattern, this->play_para.sendPattern, PATTERN_SIZE); + result = SendReferences (Video_Timer_Global::timerGroup, Video_Timer_Global::timerFrame); + if (result < 0) + return result; + Video_Timer_Global::StartTimer (); + + // Sends the first frame of the video... + result = play_send (0); + return 0; +} + +int +Video_Global::init_fast_play (void) { - // ACE_DEBUG ((LM_DEBUG, - // "Video_Timer_Global::timerHandler\n")); + int result; + + result = CmdRead ( (char *)&this->fast_para, sizeof (this->fast_para)); + if (result != 0) + return result; +#ifdef NeedByteOrderConversion + this->fast_para.sn = ntohl (this->fast_para.sn); + this->fast_para.this->nextGroup = ntohl (this->fast_para.this->nextGroup); + this->fast_para.usecPerFrame = ntohl (this->fast_para.usecPerFrame); + this->fast_para.framesPerSecond = ntohl (this->fast_para.framesPerSecond); + this->fast_para.this->VStimeAdvance = ntohl (this->fast_para.this->VStimeAdvance); +#endif + + if (this->live_source) return 0; + + this->VStimeAdvance = this->fast_para.VStimeAdvance; + /* + fprintf (stderr, "this->VStimeAdvance from client: %d\n", this->VStimeAdvance); + */ + CheckGroupRange (this->fast_para.nextGroup); + this->cmdsn = this->fast_para.sn; + Video_Timer_Global::timerGroup = this->fast_para.nextGroup; + Video_Timer_Global::timerFrame = 0; + Video_Timer_Global::timerHeader = this->gopTable[Video_Timer_Global::timerGroup].systemHeader; + this->currentUPF = this->fast_para.usecPerFrame; + Video_Timer_Global::StartTimer (); + + fast_play_send (); + return 0; +} + +int +Video_Global::init_video (void) +{ + INITvideoPara para; + int failureType = 0; + int result; + /* + fprintf (stderr, "VS about to read Para.\n"); + */ + result = CmdRead ( (char *)¶, sizeof (para)); + if (result != 0) + return result; +#ifdef NeedByteOrderConversion + para.sn = ntohl (para.sn); + para.version = ntohl (para.version); + para.nameLength = ntohl (para.nameLength); +#endif + if (para.nameLength>0) + { + result = CmdRead (this->videoFile, para.nameLength); + if (result != 0) + return result; + } + if (Mpeg_Global::session_num > Mpeg_Global::session_limit || para.version != VERSION) { + char errmsg[128]; + this->cmd = CmdFAIL; + CmdWrite ( (char *)&this->cmd, 1); + if (Mpeg_Global::session_num > Mpeg_Global::session_limit) { + sprintf (errmsg, + "Too many sessions being serviced, please try again later.\n"); + } + else { + sprintf (errmsg, "Version # not match, VS %d.%02d, Client %d.%02d", + VERSION / 100, VERSION % 100, + para.version / 100, para.version % 100); + } + write_string (this->serviceSocket, errmsg); + exit (0); + } + this->cmdsn = para.sn; + /* + fprintf (stderr, "MPEG file %s got.\n", this->videoFile); + */ + this->videoFile[para.nameLength] = 0; + + if (!strncasecmp ("LiveVideo", this->videoFile, 9)) { + if (OpenLiveVideo (&this->video_format, &this->horizontalSize, + &this->verticalSize, &this->averageFrameSize, + &this->fps, &this->pelAspectRatio) == -1) { + failureType = 100; + goto failure; + } + if (this->video_format == VIDEO_MPEG2) { + failureType = 101; + goto failure; + } + this->live_source = 1; + + this->fileSize =0x7fffffff; + this->maxS = this->maxG = this->maxI = this->maxP = this->maxB = this->minS = this->minG = this->minI = this->minP = this->minB = 1; + this->numS = this->numG = this->numF = this->numI = 0x7fffffff; + this->numP = this->numB = 0; + this->vbvBufferSize = 1; + this->firstGopFrames = 1; + this->patternSize = 1; + this->pattern[0] = 'I'; + this->pattern[1] = 0; + this->packetBufSize = this->verticalSize * this->horizontalSize * 3; + this->packet = (VideoPacket *)malloc (sizeof (VideoMessage) + sizeof (VideoPacket) + + this->packetBufSize); + if (this->packet == NULL) + { + perror ("Error: VS error on malloc this->packet buffer"); + exit (1); + } + this->packet = (VideoPacket *) ( (char *)this->packet + sizeof (VideoMessage)); - int val2, val3; - int usec = VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF; + } + else { + static double pictureRateTable[] = {23.976, 24, 25, 29.97, 30, 50, 59.94, 60}; + + this->video_format = VIDEO_MPEG1; + failureType = init_MPEG1_video_file (); + if (failureType) goto failure; + this->fps = pictureRateTable[this->pictureRate - 1]; + } + + { + INITvideoReply reply; + + reply.totalHeaders = htonl (this->numS); + reply.totalGroups = htonl (this->numG); + reply.totalFrames = htonl (this->numF); + reply.sizeIFrame = htonl (this->maxI); + reply.sizePFrame = htonl (this->maxP); + reply.sizeBFrame = htonl (this->maxB); + reply.sizeSystemHeader = htonl (this->maxS); + reply.sizeGop = htonl (this->maxG); + reply.averageFrameSize = htonl (this->averageFrameSize); + reply.verticalSize = htonl (this->verticalSize); + reply.horizontalSize = htonl (this->horizontalSize); + reply.pelAspectRatio = htonl (this->pelAspectRatio); + reply.pictureRate1000 = htonl ( (int) (this->fps * 1000)); + reply.vbvBufferSize = htonl (this->vbvBufferSize); + reply.firstGopFrames = htonl (this->firstGopFrames); + reply.patternSize = htonl (this->patternSize); + strncpy (reply.pattern, this->pattern, PATTERN_SIZE); + + reply.live = htonl (this->live_source); + reply.format = htonl (this->video_format); - if (Mpeg_Global::drift_ppm) { - usec -= (int)((double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0); + CmdWrite ( (char *)&this->cmd, 1); + + CmdWrite ( (char *)&reply, sizeof (reply)); + + /* write the first SH, GOP and IFrame to this->serviceSocket (TCP), + using code for SendPacket () */ + { + int tmpSocket = this->videoSocket; + + if (this->live_source) StartPlayLiveVideo (); + + this->videoSocket = this->serviceSocket; + + if (this->live_source) { + int frame = 0; + SendPicture (&frame); + } + else if (this->video_format == VIDEO_MPEG1) { + SendPacket (1, 0, 0, 0); + } + else { + fprintf (stderr, "VS: this->video_format %d not supported.\n", + this->video_format); + } + this->videoSocket = tmpSocket; + + if (this->live_source) StopPlayLiveVideo (); } + + return 0; - if (timerAdjust > 1) - usec = (int)(((double)usec * (double)(SPEEDUP_INV_SCALE - 1)) / - (double)SPEEDUP_INV_SCALE); - val3 = get_duration(preTimerVal, (val2 = get_usec())); + } + failure: + { + char * msg; + char errmsg[64]; + this->cmd = CmdFAIL; + sprintf (errmsg, "VS failed to alloc internal buf (type %d)", failureType); + CmdWrite ( (char *)&this->cmd, 1); + msg = failureType == 1 ? "not a complete MPEG stream" : + failureType == 2 ? "can't open MPEG file" : + failureType == 3 ? "MPEG file is not seekable" : + failureType == 4 ? "not an MPEG stream" : + failureType == 5 ? + "too many frames in MPEG file, need change MAX_FRAMES and recompile VS" : + failureType == 100 ? "failed to connect to live video source" : + failureType == 101 ? "live MPEG2 not supported" : + errmsg; + write_string (this->serviceSocket, msg); + exit (0); + } +} + +//-------------------------------------------------------- +// Video_Timer_Global methods +void +Video_Timer_Global::StartTimer (void) +{ + VIDEO_SINGLETON::instance ()->addedUPF = 0; + VIDEO_SINGLETON::instance ()->addedSignals = 0; + timerAdjust = (VIDEO_SINGLETON::instance ()->VStimeAdvance * SPEEDUP_INV_SCALE) / VIDEO_SINGLETON::instance ()->currentUPF; + /* + SFprintf (stderr, "VS StartTimer (): fast-start frames %d\n", + timerAdjust / SPEEDUP_INV_SCALE); + */ + TimerSpeed (); + // setsignal (SIGALRM, timerHandler); + timerOn = 1; + preTimerVal = get_usec (); + /* + fprintf (stderr, "VS: timer started at %d upf.\n", VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF); + */ +} + +void +Video_Timer_Global::StopTimer (void) +{ + struct itimerval val; + // ## I have to incorporate this logic into the changed code + // setsignal (SIGALRM, SIG_IGN); + val.it_interval.tv_sec = val.it_value.tv_sec = 0; + val.it_interval.tv_usec = val.it_value.tv_usec = 0; + setitimer (ITIMER_REAL, &val, NULL); + timerOn = 0; + /* + fprintf (stderr, "VS: timer stopped.\n"); + */ +} + +void +Video_Timer_Global::TimerSpeed (void) +{ + struct itimerval val; + int usec = VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF; + if (Mpeg_Global::drift_ppm) { /* - if (val3 >= usec<< 1)) - fprintf(stderr, "Slower: %d out of VIDEO_SINGLETON::instance ()->currentUPF %d.\n", - val3, usec); + int drift = (double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0; + SFprintf (stderr, "Mpeg_Global::drift_ppm %d, usec %d, drift %d, new usec %d\n", + Mpeg_Global::drift_ppm, usec, drift, usec - drift); + */ + usec -= (int) ( (double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0); + } + if (timerAdjust > 1) + usec = (int) ( ( (double)usec * (double) (SPEEDUP_INV_SCALE - 1)) / + (double)SPEEDUP_INV_SCALE); + val.it_interval.tv_sec = val.it_value.tv_sec = usec / 1000000; + val.it_interval.tv_usec = val.it_value.tv_usec = usec % 1000000; + setitimer (ITIMER_REAL, &val, NULL); + /* + SFprintf (stderr, + "VS TimerSpeed () at %s speed, timerAdjust %d VIDEO_SINGLETON::instance ()->addedSignals %d.\n", + (timerAdjust > 1) ? "higher" : "normal", timerAdjust, VIDEO_SINGLETON::instance ()->addedSignals); + */ + +} + +void +Video_Timer_Global::TimerProcessing (void) +{ +/* + fprintf (stderr, "VS: timerHandler...\n"); +*/ + if (!timerOn) { + return; + } + if (timerAdjust < 0) + { + timerAdjust += SPEEDUP_INV_SCALE; + return; + } + if (timerAdjust >0) + { + if ( (--timerAdjust) == 0) + TimerSpeed (); + } + if (VIDEO_SINGLETON::instance ()->cmd == CmdPLAY) + { + if (timerGroup == VIDEO_SINGLETON::instance ()->numG - 1 && timerFrame >= VIDEO_SINGLETON::instance ()->gopTable[timerGroup].totalFrames - 1) + { + timerFrame ++; /* force sending of END_SEQ when PLAY VIDEO_SINGLETON::instance ()->cmd */ + StopTimer (); + return; + } else - fprintf(stderr, "+\n"); - */ - preTimerVal = val2; - if (val3 < 0 || val3 > 100000000) - val3 = usec; - val2 = (val3 + (usec>>1)) / usec; - if (val2 < 0) val2 = 0; - if (val2) { - TimerProcessing(); - val2 --; - } - VIDEO_SINGLETON::instance ()->addedSignals += val2; - - if (VIDEO_SINGLETON::instance ()->addedSignals) { - val2 = timerAdjust; - if (timerAdjust < MAX_TIMER_ADJUST) { - timerAdjust += VIDEO_SINGLETON::instance ()->addedSignals * SPEEDUP_INV_SCALE; - if (val2 < SPEEDUP_INV_SCALE) { - TimerSpeed(); - } - } - else { - /* - fprintf(stderr, "VS timerAdjust %d, VIDEO_SINGLETON::instance ()->addedSignals %d, timerFrame %d\n", - timerAdjust, VIDEO_SINGLETON::instance ()->addedSignals, timerFrame); - */ - for (val3 = 0; val3 < VIDEO_SINGLETON::instance ()->addedSignals; val3 ++) - TimerProcessing(); - } - VIDEO_SINGLETON::instance ()->addedSignals = 0; + { + timerFrame ++; + if (timerFrame >= VIDEO_SINGLETON::instance ()->gopTable[timerGroup].totalFrames) + { + timerGroup ++; + timerFrame = 0; + timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; + } + } + } + else { + if (VIDEO_SINGLETON::instance ()->cmd == CmdFF) { + if (timerGroup == VIDEO_SINGLETON::instance ()->numG - 1) { + StopTimer (); + return; + } + timerGroup ++; + timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; + } + else { + if (timerGroup == 0) { + StopTimer (); + return; + } + timerGroup --; + timerHeader = VIDEO_SINGLETON::instance ()->gopTable[timerGroup].systemHeader; + } + } + +} + +void +Video_Timer_Global::timerHandler (int sig) +{ + // ACE_DEBUG ( (LM_DEBUG, + // "Video_Timer_Global::timerHandler\n")); + + int val2, val3; + int usec = VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF; + + if (Mpeg_Global::drift_ppm) { + usec -= (int) ( (double)usec * (double)Mpeg_Global::drift_ppm / 1000000.0); + } + + if (timerAdjust > 1) + usec = (int) ( ( (double)usec * (double) (SPEEDUP_INV_SCALE - 1)) / + (double)SPEEDUP_INV_SCALE); + val3 = get_duration (preTimerVal, (val2 = get_usec ())); + /* + if (val3 >= usec<< 1)) + fprintf (stderr, "Slower: %d out of VIDEO_SINGLETON::instance ()->currentUPF %d.\n", + val3, usec); + else + fprintf (stderr, "+\n"); + */ + preTimerVal = val2; + if (val3 < 0 || val3 > 100000000) + val3 = usec; + val2 = (val3 + (usec>>1)) / usec; + if (val2 < 0) val2 = 0; + if (val2) { + TimerProcessing (); + val2 --; + } + VIDEO_SINGLETON::instance ()->addedSignals += val2; + + if (VIDEO_SINGLETON::instance ()->addedSignals) { + val2 = timerAdjust; + if (timerAdjust < MAX_TIMER_ADJUST) { + timerAdjust += VIDEO_SINGLETON::instance ()->addedSignals * SPEEDUP_INV_SCALE; + if (val2 < SPEEDUP_INV_SCALE) { + TimerSpeed (); + } } + else { + /* + fprintf (stderr, "VS timerAdjust %d, VIDEO_SINGLETON::instance ()->addedSignals %d, timerFrame %d\n", + timerAdjust, VIDEO_SINGLETON::instance ()->addedSignals, timerFrame); + */ + for (val3 = 0; val3 < VIDEO_SINGLETON::instance ()->addedSignals; val3 ++) + TimerProcessing (); + } + VIDEO_SINGLETON::instance ()->addedSignals = 0; + } } diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.h b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.h index 3053271bf7b..a11b925c35c 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.h +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Globals.h @@ -60,6 +60,37 @@ #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 +// Global definitions +#define nextByte {int val; fileptr ++; \ + if ((val = getc(VIDEO_SINGLETON::instance ()->fp)) == EOF) \ + {\ + perror("Crossed EOF or error while scanning"); \ + return 1; \ + } nb = val;} + +#define computePicSize \ + if (inpic) \ + { \ + if (pictype == 'I') \ + { \ + VIDEO_SINGLETON::instance ()->maxI = max(VIDEO_SINGLETON::instance ()->maxI, (int)(fileptr - picptr - 4)); \ + VIDEO_SINGLETON::instance ()->minI = min(VIDEO_SINGLETON::instance ()->minI, (int)(fileptr - picptr - 4)); \ + } \ + else if (pictype == 'P') \ + { \ + VIDEO_SINGLETON::instance ()->maxP = max(VIDEO_SINGLETON::instance ()->maxP, (int)(fileptr - picptr - 4)); \ + VIDEO_SINGLETON::instance ()->minP = min(VIDEO_SINGLETON::instance ()->minP, (int)(fileptr - picptr - 4)); \ + } \ + else \ + { \ + VIDEO_SINGLETON::instance ()->maxB = max(VIDEO_SINGLETON::instance ()->maxB, (int)(fileptr - picptr - 4)); \ + VIDEO_SINGLETON::instance ()->minB = min(VIDEO_SINGLETON::instance ()->minB, (int)(fileptr - picptr - 4)); \ + } \ + VIDEO_SINGLETON::instance ()->frameTable[ftptr].type = pictype; \ + VIDEO_SINGLETON::instance ()->frameTable[ftptr++].size = (int)(fileptr - picptr - 4); \ + inpic = 0; \ + } + #define FileRead(position, buf, size) \ { \ @@ -85,13 +116,16 @@ { fprintf(stderr, "VS: %d.VIDEO_SINGLETON::instance ()->nextGroup(%d) out of range (%d).\n", VIDEO_SINGLETON::instance ()->cmd, (pnextGroup), VIDEO_SINGLETON::instance ()->numG); \ return 0; } } -// Global definitions - #include <sys/types.h> #include <sys/socket.h> -#include "../include/common.h" #include "ace/Singleton.h" +#include "../include/common.h" #include "../mpeg_shared/routine.h" +#include "../mpeg_shared/fileio.h" +#include "../mpeg_shared/com.h" +#include "../mpeg_shared/sendpt.h" +#include "proto.h" +#include "Video_Server.h" class Mpeg_Global { @@ -219,9 +253,36 @@ class Video_Global // fast video play locals FFpara fast_para; + PLAYpara play_para; int fast_preGroup; int fast_preHeader; - + + // globals functions + int CmdRead (char *buf, int psize); + int CmdWrite (char *buf, int size); + int SendPacket (int shtag, int gop, int frame, int timeToUse); + int FBread (char *buf, int size); + int PLAYliveVideo (PLAYpara * para); + void ComputeFirstSendPattern (float limit); + int FrameToGroup (int * frame); + int SendReferences (int group, int frame); + int send_to_network (int timeToUse); + void GetFeedBack (void); + int SendPicture (int *frame); + int ReadInfoFromFile (void); + void WriteInfoToFile (void); + int init_MPEG1_video_file (void); + int play_send (int debug=0); + int fast_play_send (void); + int position (void); + int step_video (void); + int fast_forward (void); + int fast_backward (void); + int stat_stream (void); + int stat_sent (void); + int init_play (void); + int init_fast_play (void); + int init_video (void); }; typedef ACE_TSS_Singleton <Video_Global, ACE_SYNCH_MUTEX> VIDEO_SINGLETON; diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.cpp index 30b66af03d5..56e61ff2c20 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.cpp +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.cpp @@ -19,6 +19,7 @@ Video_Control_State::get_state (void) Video_Control_Waiting_State::Video_Control_Waiting_State (void) { + //%% this->state_ = VIDEO_WAITING; } @@ -30,7 +31,7 @@ Video_Control_Waiting_State::handle_input (ACE_HANDLE h) fprintf (stderr, "VS: waiting for a new command...\n"); VIDEO_SINGLETON::instance ()->precmd = VIDEO_SINGLETON::instance ()->cmd; - result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); + result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); if (result != 0) { cerr << result; @@ -44,25 +45,25 @@ Video_Control_Waiting_State::handle_input (ACE_HANDLE h) { case CmdPOSITION: case CmdPOSITIONrelease: - result = Video_Server::position (); + result = VIDEO_SINGLETON::instance ()->position (); if (result != 0) return result; break; case CmdSTEP: - result = Video_Server::step_video (); + result = VIDEO_SINGLETON::instance ()->step_video (); if (result != 0) return result; break; case CmdFF: - Video_Server::init_fast_play (); + VIDEO_SINGLETON::instance ()->init_fast_play (); this->vch_->change_state (VIDEO_CONTROL_FAST_FORWARD_STATE::instance ()); break; case CmdFB: - Video_Server::init_fast_play (); + VIDEO_SINGLETON::instance ()->init_fast_play (); this->vch_->change_state (VIDEO_CONTROL_FAST_BACKWARD_STATE::instance ()); break; case CmdPLAY: - Video_Server::init_play (); + VIDEO_SINGLETON::instance ()->init_play (); this->vch_->change_state (VIDEO_CONTROL_PLAY_STATE::instance ()); break; case CmdCLOSE: @@ -70,10 +71,10 @@ Video_Control_Waiting_State::handle_input (ACE_HANDLE h) ACE_Reactor::instance ()->end_event_loop (); break; case CmdSTATstream: - Video_Server::stat_stream (); + VIDEO_SINGLETON::instance ()->stat_stream (); break; case CmdSTATsent: - Video_Server::stat_sent (); + VIDEO_SINGLETON::instance ()->stat_sent (); break; default: ACE_DEBUG ((LM_DEBUG, @@ -98,7 +99,7 @@ Video_Control_Play_State::handle_input (ACE_HANDLE h) fprintf (stderr,"Video_Control_Play_State::handle_input () \n"); char tmp; - int result = Video_Server::CmdRead((char *)&tmp, 1); + int result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&tmp, 1); if (result != 0) return result; @@ -108,7 +109,7 @@ Video_Control_Play_State::handle_input (ACE_HANDLE h) } else if (tmp == CmdSTOP) { VIDEO_SINGLETON::instance ()->cmd = tmp; - result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); + result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); if (result != 0) return result; #ifdef NeedByteOrderConversion @@ -119,7 +120,7 @@ Video_Control_Play_State::handle_input (ACE_HANDLE h) // VIDEO_SINGLETON::instance ()->state = Video_Global::INVALID; // We need to call the read_cmd of the Video_Server to simulate // the control going to a switch.. - // Video_Server::read_cmd (); + // VIDEO_SINGLETON::instance ()->read_cmd (); // Change the state of the video control handler to waiting state // to read further commands. @@ -132,7 +133,7 @@ Video_Control_Play_State::handle_input (ACE_HANDLE h) /* fprintf(stderr, "VS: VIDEO_SINGLETON::Instance ()->CmdSPEED. . .\n"); */ - result = Video_Server::CmdRead((char *)¶, sizeof(para)); + result = VIDEO_SINGLETON::instance ()->CmdRead((char *)¶, sizeof(para)); if (result != 0) return result; #ifdef NeedByteOrderConversion @@ -168,7 +169,7 @@ Video_Control_Fast_Forward_State::Video_Control_Fast_Forward_State (void) int Video_Control_Fast_Forward_State::handle_input (ACE_HANDLE h) { - int result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); + int result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); if (result != 0) return result; if (VIDEO_SINGLETON::instance ()->cmd == CmdCLOSE) { @@ -183,7 +184,7 @@ Video_Control_Fast_Forward_State::handle_input (ACE_HANDLE h) return 1; // exit(1); } - result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); + result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); if (result != 0 ) return result; #ifdef NeedByteOrderConversion @@ -191,7 +192,7 @@ Video_Control_Fast_Forward_State::handle_input (ACE_HANDLE h) #endif Video_Timer_Global::StopTimer(); // VIDEO_SINGLETON::instance ()->state = Video_Global::INVALID; - // Video_Server::read_cmd (); + // VIDEO_SINGLETON::instance ()->read_cmd (); //Change the video control handler's state to read further commands this->vch_->change_state (VIDEO_CONTROL_WAITING_STATE::instance ()); @@ -206,7 +207,7 @@ Video_Control_Fast_Backward_State::Video_Control_Fast_Backward_State (void) int Video_Control_Fast_Backward_State::handle_input (ACE_HANDLE h) { - int result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); + int result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmd, 1); if (result != 0) return result; if (VIDEO_SINGLETON::instance ()->cmd == CmdCLOSE) { @@ -221,7 +222,7 @@ Video_Control_Fast_Backward_State::handle_input (ACE_HANDLE h) return 1; // exit(1); } - result = Video_Server::CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); + result = VIDEO_SINGLETON::instance ()->CmdRead((char *)&VIDEO_SINGLETON::instance ()->cmdsn, sizeof(int)); if (result != 0 ) return result; #ifdef NeedByteOrderConversion @@ -229,7 +230,7 @@ Video_Control_Fast_Backward_State::handle_input (ACE_HANDLE h) #endif Video_Timer_Global::StopTimer(); // VIDEO_SINGLETON::instance ()->state = Video_Global::INVALID; - // Video_Server::read_cmd (); + // VIDEO_SINGLETON::instance ()->read_cmd (); //Change the video control handler's state to read further commands this->vch_->change_state (VIDEO_CONTROL_WAITING_STATE::instance ()); diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.h b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.h index d091c604537..df37a959d1f 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.h +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Control_State.h @@ -36,6 +36,14 @@ class Video_Control_Handler; class Video_Control_State { + // =TITLE + // Defines an abstract class that is used to implement the state + // pattern for the video control. + // + // =DESCRIPTION + // The various states of the video control are defined by the + // Video_States enum. They can be implemented by subclassing from + // this class and overriding the handle_input method. public: Video_Control_State (); // constructor @@ -72,45 +80,64 @@ protected: class Video_Control_Waiting_State : public virtual Video_Control_State { + // =TITLE + // Defines a class that implements the waiting state of the video + // control state pattern. + public: Video_Control_Waiting_State (void); // Default constructor, sets the state to WAITING virtual int handle_input (ACE_HANDLE h = 0); - // Called by the Video_Control_handler when in the waiting state + // Called by the Video_Control_handler when control events occur in + // the waiting state }; class Video_Control_Play_State : public virtual Video_Control_State { + // =TITLE + // Defines a class that implements the playing state of the video + // control state pattern. public: Video_Control_Play_State (void); // Default constructor, sets the state to VIDEO_PLAY virtual int handle_input (ACE_HANDLE h = 0); + // Called by the Video_Control_handler when control events occur in + // the playing state }; class Video_Control_Fast_Forward_State : public virtual Video_Control_State { + // =TITLE + // Defines a class that implements the fast_forward state of the video + // control state pattern. public: Video_Control_Fast_Forward_State (void); // Default constructor, sets the state to VIDEO_FAST_FORWARD virtual int handle_input (ACE_HANDLE h = 0); + // Called by the Video_Control_handler when control events occur in + // the fast_forward state }; class Video_Control_Fast_Backward_State : public virtual Video_Control_State { + // =TITLE + // Defines a class that implements the fast_backward state of the video + // control state pattern. public: Video_Control_Fast_Backward_State (void); // Default constructor, sets the state to VIDEO_FAST_BACKWARD virtual int handle_input (ACE_HANDLE h = 0); - + // Called by the Video_Control_handler when control events occur in + // the fast_backward state }; typedef ACE_TSS_Singleton <Video_Control_Waiting_State, ACE_SYNCH_MUTEX> VIDEO_CONTROL_WAITING_STATE; diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.cpp index 19f59d672d2..d44e0354b96 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.cpp +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.cpp @@ -27,133 +27,8 @@ #include "Video_Server.h" -// Global Methods - -PLAYpara Video_Server::para; - -// %% maybe put this in some class? -// this sends one frame -int -play_send (int debug) -{ - - // ACE_DEBUG((LM_DEBUG,"play_send: sending the frame \n")); - int curGroup = Video_Timer_Global::timerGroup; - int curFrame = Video_Timer_Global::timerFrame; - int curHeader = Video_Timer_Global::timerHeader; - char * sp; - - if (VIDEO_SINGLETON::instance ()->preGroup != curGroup || - curFrame != VIDEO_SINGLETON::instance ()->preFrame) - { - int sendStatus = -1; - int frameStep = 1; - if (debug) - cerr << " curgroup = " << curGroup << endl ; - if (curGroup == 0) - { - - int i = curFrame + 1; - while (i < VIDEO_SINGLETON::instance ()->firstPatternSize && - !VIDEO_SINGLETON::instance ()->firstSendPattern[i]) - { - frameStep ++; - i++; - } - } - else /* (curGroup > 0) */ - { - int i = curFrame + 1; - sp = VIDEO_SINGLETON::instance ()->sendPattern + ((curGroup - 1) % VIDEO_SINGLETON::instance ()->sendPatternGops) * VIDEO_SINGLETON::instance ()->patternSize; - while (i < VIDEO_SINGLETON::instance ()->patternSize && !sp[i]) - { - frameStep ++; - i++; - } - } - if (curGroup == 0) - { - if (debug) - cerr << "first : " << - VIDEO_SINGLETON::instance ()->firstSendPattern[curFrame] << endl; - if (VIDEO_SINGLETON::instance ()->firstSendPattern[curFrame]) - sendStatus = 0; - else /* (!VIDEO_SINGLETON::instance ()->firstVIDEO_SINGLETON::instance ()->SendVIDEO_SINGLETON::Instance ()->Pattern[curFrame]) */ - { - int i = curFrame - 1; - while (i > 0 && !VIDEO_SINGLETON::instance ()->firstSendPattern[i]) - i--; - if (i > VIDEO_SINGLETON::instance ()->preFrame) - /* the frame (curGroup, i) hasn't been sent yet */ - { - sendStatus = 0; - curFrame = i; - } - else - sendStatus = -1; - if (debug) - cerr << "SendStatus = " << sendStatus << endl; - } - } - else if (sp[curFrame]) /* curGroup > 0 */ - sendStatus = 0; - else /* (!sp[curFrame]) */ - { - int i = curFrame - 1; - while (i > 0 && !sp[i]) - i--; - if (curGroup == VIDEO_SINGLETON::instance ()->preGroup && i > VIDEO_SINGLETON::instance ()->preFrame) - /* the frame (curGroup, i) hasn't been sent yet */ - { - sendStatus = 0; - curFrame = i; - } - else - sendStatus = -1; - } - if (!sendStatus) - { - // Send the current video frame, calls send_to_network which - // fragments and sends via blocking write . - sendStatus = Video_Server::SendPacket(VIDEO_SINGLETON::instance ()->preHeader != curHeader, - curGroup, curFrame, - (VIDEO_SINGLETON::instance ()->currentUPF + VIDEO_SINGLETON::instance ()->addedUPF) * frameStep); - if (!sendStatus) - { - VIDEO_SINGLETON::instance ()->preHeader = curHeader; - VIDEO_SINGLETON::instance ()->preGroup = curGroup; - VIDEO_SINGLETON::instance ()->preFrame = curFrame; -#ifdef STAT - if (Video_Server::para.collectStat) - { - int f = VIDEO_SINGLETON::instance ()->gopTable[curGroup].previousFrames + curFrame; - VIDEO_SINGLETON::instance ()->framesSent[f>>3] |= (1 << (f % 8)); - } -#endif - } - } - } - return 0; -} - -int -fast_play_send (void) -{ - if (VIDEO_SINGLETON::instance ()->fast_preGroup != Video_Timer_Global::timerGroup) - { - Video_Server::SendPacket(VIDEO_SINGLETON::instance ()->fast_preHeader != Video_Timer_Global::timerHeader, Video_Timer_Global::timerGroup, 0, - VIDEO_SINGLETON::instance ()->fast_para.usecPerFrame * VIDEO_SINGLETON::instance ()->patternSize >> 2); - VIDEO_SINGLETON::instance ()->fast_preHeader = Video_Timer_Global::timerHeader; - VIDEO_SINGLETON::instance ()->fast_preGroup = Video_Timer_Global::timerGroup; - } - return 0; -} - // Video_Sig_Handler methods // handles the timeout SIGALRM signal -// %% this should *not* register itself,but it should -// be registered by the Video_Server::run, alongwith -// the remaining handlers. Video_Sig_Handler::Video_Sig_Handler (Video_Control_Handler *vch) : vch_ (vch) { @@ -243,15 +118,15 @@ Video_Sig_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *) switch (this->vch_->get_state ()->get_state ()) { case Video_Control_State::VIDEO_PLAY: - play_send (); + VIDEO_SINGLETON::instance ()->play_send (); break; case Video_Control_State::VIDEO_FAST_FORWARD: // this handles the forward play case! - fast_play_send (); + VIDEO_SINGLETON::instance ()->fast_play_send (); break; case Video_Control_State::VIDEO_FAST_BACKWARD: // this handles the backward play case! - fast_play_send (); + VIDEO_SINGLETON::instance ()->fast_play_send (); break; default: break; @@ -289,13 +164,13 @@ Video_Data_Handler::handle_input (ACE_HANDLE handle) switch (this->vch_->get_state ()->get_state ()) { case Video_Control_State::VIDEO_PLAY: - GetFeedBack (); - play_send (); // simulating the for loop in playvideo () in vs.cpp + VIDEO_SINGLETON::instance ()->GetFeedBack (); + VIDEO_SINGLETON::instance ()->play_send (); // simulating the for loop in playvideo () in vs.cpp break; case Video_Control_State::VIDEO_FAST_FORWARD: case Video_Control_State::VIDEO_FAST_BACKWARD: - GetFeedBack (); - fast_play_send (); // simulating the for loop in fast_play + VIDEO_SINGLETON::instance ()->GetFeedBack (); + VIDEO_SINGLETON::instance ()->fast_play_send (); // simulating the for loop in fast_play break; } return 0; @@ -306,15 +181,17 @@ Video_Data_Handler::handle_input (ACE_HANDLE handle) Video_Control_Handler::Video_Control_Handler (int control_fd) : control_handle_ (control_fd) { - VIDEO_CONTROL_HANDLER_INSTANCE::instance ()->set_video_control_handler (this); } +// Called by the reactor to extract the handle associated with this handler. ACE_HANDLE Video_Control_Handler::get_handle (void) const { return this->control_handle_ ; } +// Called by the Reactor when data is ready to be read from the +// video control handle, which indicates a control message from the client. int Video_Control_Handler::handle_input (ACE_HANDLE handle) { @@ -322,40 +199,47 @@ Video_Control_Handler::handle_input (ACE_HANDLE handle) // state pattern } +// Returns the current state object . Video_Control_State * Video_Control_Handler::get_state (void) { return this->state_; } +// Changes the state of the video control handler from the current +// state to the state represented by the argument. void Video_Control_Handler::change_state (Video_Control_State *state) { ACE_DEBUG ((LM_DEBUG, - "Video_Control_Handler::Changing to state %d\n", + "(%P|%t) Video_Control_Handler::Changing to state %d\n", state->get_state ())); this->state_ = state; } // ---------------------------------------------------------------------- +// Video_Control_Handler_Instance methods. +// Default constructor Video_Control_Handler_Instance::Video_Control_Handler_Instance (void) { } +// Sets the video_control_handler associated with this instance singleton. void Video_Control_Handler_Instance::set_video_control_handler (Video_Control_Handler *h) { this->video_control_handler_ = h; } +// Accessor method to the associated video_control_handler Video_Control_Handler * Video_Control_Handler_Instance::get_video_control_handler (void) { return this->video_control_handler_; } -// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- // Video_Server methods // Do-nothing default constructor. @@ -363,6 +247,8 @@ Video_Server::Video_Server () { } +// Constructor with arguments control_fd,data_fd,real-time tag,maximum +// packet size.Calls the init methods with these arguments. Video_Server::Video_Server (int ctr_fd, int data_fd, int rttag, @@ -390,12 +276,18 @@ Video_Server::init (int ctr_fd, int rttag, int max_pkt_size) { + int result; + + // Associate the default ACE_Reactor instance as the reactor . this->reactor_ = ACE_Reactor::instance (); + // Create the control,data and signal handlers. ACE_NEW_RETURN (this->control_handler_, Video_Control_Handler (ctr_fd), -1); + VIDEO_CONTROL_HANDLER_INSTANCE::instance ()->set_video_control_handler (this->control_handler_); + ACE_NEW_RETURN (this->data_handler_ , Video_Data_Handler (data_fd, this->control_handler_), @@ -405,8 +297,7 @@ Video_Server::init (int ctr_fd, Video_Sig_Handler (this->control_handler_), -1); - int result; - + // Set the global socket fd's from the arguments. VIDEO_SINGLETON::instance ()->serviceSocket = ctr_fd; VIDEO_SINGLETON::instance ()->videoSocket = data_fd; VIDEO_SINGLETON::instance ()->conn_tag = max_pkt_size; @@ -421,36 +312,30 @@ Video_Server::init (int ctr_fd, VIDEO_SINGLETON::instance ()->start_time = time(NULL); - atexit(on_exit_routine); + // Set the atexit routine + atexit (on_exit_routine); VIDEO_SINGLETON::instance ()->lastRef[0] = VIDEO_SINGLETON::instance ()->lastRef[1] = -1; VIDEO_SINGLETON::instance ()->lastRefPtr = 0; - INITvideo(); + VIDEO_SINGLETON::instance ()->init_video (); if (rttag) { if (SetRTpriority("VS", 0) == -1) rttag = 0; } // sets the video control handler state to be waiting - this->control_handler_->change_state (VIDEO_CONTROL_WAITING_STATE::instance ()); return 0; } -// %% currently this only registers handlers -// and handles the FIRST command. that needs -// to be changed, and then maybe this -// needs tobe renamed to register_handles or something -// like that int -Video_Server::run (void) +Video_Server::register_handlers (void) { int result; // Register the event handlers with the default ACE_REACTOR. - // first the data handler, i.e. UDP result = this->reactor_->register_handler (this->data_handler_, ACE_Event_Handler::READ_MASK); @@ -490,237 +375,6 @@ Video_Server::run (void) return 0; } -int -Video_Server::init_play (void) -{ - int result; - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Video_Server::play ()")); - - // this gets the parameters for the play command - result = Video_Server::CmdRead((char *)¶, sizeof(para)); - if (result != 0) - return result; -#ifdef NeedByteOrderConversion - para.sn = ntohl(para.sn); - para.VIDEO_SINGLETON::instance ()->nextFrame = ntohl(para.VIDEO_SINGLETON::instance ()->nextFrame); - para.usecPerFrame = ntohl(para.usecPerFrame); - para.framesPerSecond = ntohl(para.framesPerSecond); - para.VIDEO_SINGLETON::instance ()->frameRateLimit1000 = ntohl(para.VIDEO_SINGLETON::instance ()->frameRateLimit1000); - para.collectStat = ntohl(para.collectStat); - para.VIDEO_SINGLETON::instance ()->sendPatternGops = ntohl(para.VIDEO_SINGLETON::instance ()->sendPatternGops); - para.VIDEO_SINGLETON::instance ()->VStimeAdvance = ntohl(para.VIDEO_SINGLETON::instance ()->VStimeAdvance); -#endif - - VIDEO_SINGLETON::instance ()->frameRateLimit = para.frameRateLimit1000 / 1000.0; - VIDEO_SINGLETON::instance ()->cmdsn = para.sn; - VIDEO_SINGLETON::instance ()->currentUPF = para.usecPerFrame; - VIDEO_SINGLETON::instance ()->VStimeAdvance = para.VStimeAdvance; - - { - int ts = htonl(get_usec()); - Video_Server::CmdWrite((char *)&ts, sizeof(int)); - } - - if (VIDEO_SINGLETON::instance ()->live_source || VIDEO_SINGLETON::instance ()->video_format != VIDEO_MPEG1) { - if (VIDEO_SINGLETON::instance ()->live_source) - PLAYliveVideo (¶); - return 0; - } - - fprintf(stderr, "VIDEO_SINGLETON::instance ()->VStimeAdvance from client: %d\n", VIDEO_SINGLETON::instance ()->VStimeAdvance); - - VIDEO_SINGLETON::instance ()->sendPatternGops = para.sendPatternGops; - ComputeFirstSendPattern(VIDEO_SINGLETON::instance ()->frameRateLimit); -#ifdef STAT - if (para.collectStat) - memset(VIDEO_SINGLETON::instance ()->framesSent, 0, (VIDEO_SINGLETON::instance ()->numF + 7)>>3); -#endif - CheckFrameRange(para.nextFrame); - Video_Timer_Global::timerFrame = para.nextFrame; - Video_Timer_Global::timerGroup = FrameToGroup(&Video_Timer_Global::timerFrame); - Video_Timer_Global::timerHeader = VIDEO_SINGLETON::instance ()->gopTable[Video_Timer_Global::timerGroup].systemHeader; - memcpy(VIDEO_SINGLETON::instance ()->sendPattern, para.sendPattern, PATTERN_SIZE); - result = SendReferences(Video_Timer_Global::timerGroup, Video_Timer_Global::timerFrame); - if (result < 0) - return result; - Video_Timer_Global::StartTimer (); - - // Sends the first frame of the video... - result = play_send (0); - return 0; -} - -int -Video_Server::SendPacket (int shtag,int gop,int frame,int timeToUse) -/* frame maybe out of range (PLAY, STEP), in this case, END_SEQ is sent - to force display of last frame in VD */ -{ - char * buf = ((char *) VIDEO_SINGLETON::instance ()->packet) + sizeof(VideoPacket); - int f = VIDEO_SINGLETON::instance ()->gopTable[gop].previousFrames + frame; - int sh = VIDEO_SINGLETON::instance ()->gopTable[gop].systemHeader; - /* - SFprintf(stderr, "VS to send VIDEO_SINGLETON::instance ()->packet gop-%d, frame-%d.\n", gop, frame); - */ - - VIDEO_SINGLETON::instance ()->packet->currentUPF = ntohl(VIDEO_SINGLETON::instance ()->currentUPF); - - if (frame >= VIDEO_SINGLETON::instance ()->gopTable[gop].totalFrames) - { - VIDEO_SINGLETON::instance ()->packet->cmd = htonl(VIDEO_SINGLETON::instance ()->cmd); - VIDEO_SINGLETON::instance ()->packet->cmdsn = htonl(VIDEO_SINGLETON::instance ()->cmdsn); - VIDEO_SINGLETON::instance ()->packet->sh = htonl(sh); - VIDEO_SINGLETON::instance ()->packet->gop = htonl(gop); - VIDEO_SINGLETON::instance ()->packet->frame = htonl(VIDEO_SINGLETON::instance ()->numF); - VIDEO_SINGLETON::instance ()->packet->display = htonl(VIDEO_SINGLETON::instance ()->numF-1); - VIDEO_SINGLETON::instance ()->packet->future = htonl((unsigned)-1); - VIDEO_SINGLETON::instance ()->packet->past = htonl((unsigned)-1); - VIDEO_SINGLETON::instance ()->packet->dataBytes = htonl(4); - *(int*)((char*)VIDEO_SINGLETON::instance ()->packet + sizeof(*VIDEO_SINGLETON::instance ()->packet)) = htonl(SEQ_END_CODE); - - return send_to_network(timeToUse); - } - - if (frame) - shtag = 0; - else if (VIDEO_SINGLETON::instance ()->needHeader) - { - shtag = 1; - VIDEO_SINGLETON::instance ()->needHeader = 0; - } - - VIDEO_SINGLETON::instance ()->packet->cmd = htonl(VIDEO_SINGLETON::instance ()->cmd); - VIDEO_SINGLETON::instance ()->packet->cmdsn = htonl(VIDEO_SINGLETON::instance ()->cmdsn); - VIDEO_SINGLETON::instance ()->packet->sh = htonl(sh); - VIDEO_SINGLETON::instance ()->packet->gop = htonl(gop); - VIDEO_SINGLETON::instance ()->packet->frame = htonl(f); - if (VIDEO_SINGLETON::instance ()->frameTable[f].type == 'B') - { - int pre1 = -1, pre2 = -1, i = f; - while (i>0) - if (VIDEO_SINGLETON::instance ()->frameTable[--i].type != 'B') - { - pre1 = i; - break; - } - while (i>0) - if (VIDEO_SINGLETON::instance ()->frameTable[--i].type != 'B') - { - pre2 = i; - break; - } - if (pre2 == -1) - { - /* - fprintf(stderr, - "frame %d-%d (%d) is a B without past ref, no to be sent.\n", - gop, frame, f); - */ - return -1; - } - if (pre1 != VIDEO_SINGLETON::instance ()->lastRef[VIDEO_SINGLETON::instance ()->lastRefPtr] || - pre2 != VIDEO_SINGLETON::instance ()->lastRef[1 - VIDEO_SINGLETON::instance ()->lastRefPtr]) - { - /* - fprintf(stderr, - "send of B frame %d gaveup for past %d/future %d ref not sent.\n", - f, pre2, pre1); - */ - return -1; - } - VIDEO_SINGLETON::instance ()->packet->display = htonl(f); - VIDEO_SINGLETON::instance ()->packet->future = htonl(pre1); - VIDEO_SINGLETON::instance ()->packet->past = htonl(pre2); - } - else - { - int next = f; - int pre = f; - - while (next < VIDEO_SINGLETON::instance ()->numF && VIDEO_SINGLETON::instance ()->frameTable[++next].type == 'B'); - while (pre > 0 && VIDEO_SINGLETON::instance ()->frameTable[--pre].type == 'B'); - if (VIDEO_SINGLETON::instance ()->frameTable[f].type == 'P' && pre != VIDEO_SINGLETON::instance ()->lastRef[VIDEO_SINGLETON::instance ()->lastRefPtr]) - { - /* - fprintf(stderr, - "send of P frame %d gaveup for past ref %d not sent.\n", - f, pre); - fprintf(stderr, "ref0=%d, ref1=%d, ptr=%d.\n", - VIDEO_SINGLETON::instance ()->lastRef[0], VIDEO_SINGLETON::instance ()->lastRef[1], VIDEO_SINGLETON::instance ()->lastRefPtr); - */ - return -1; - } - VIDEO_SINGLETON::instance ()->packet->display = htonl(next); - VIDEO_SINGLETON::instance ()->packet->future = htonl((unsigned)-1); - VIDEO_SINGLETON::instance ()->packet->past = htonl(VIDEO_SINGLETON::instance ()->frameTable[f].type == 'P' ? pre : (unsigned)-1); - } - { - char * ptr = buf; - int size = 0, offset = 0, i; - if (shtag) /* send system header */ - { - size = VIDEO_SINGLETON::instance ()->systemHeader[sh].size; - FileRead(VIDEO_SINGLETON::instance ()->systemHeader[sh].offset, ptr, size); - ptr += size; - } - if (!frame) /* send gop header */ - { - size = VIDEO_SINGLETON::instance ()->gopTable[gop].headerSize; - FileRead(VIDEO_SINGLETON::instance ()->gopTable[gop].offset, ptr, size); - ptr += size; - } - size = VIDEO_SINGLETON::instance ()->frameTable[f].size; - for (i=VIDEO_SINGLETON::instance ()->gopTable[gop].previousFrames; i<f; i++) - offset += VIDEO_SINGLETON::instance ()->frameTable[i].size; - FileRead((VIDEO_SINGLETON::instance ()->gopTable[gop].firstIoffset + offset), ptr, size); - ptr += size; - VIDEO_SINGLETON::instance ()->packet->dataBytes = htonl(ptr - buf); - } - - { - int sent = send_to_network(timeToUse); - if (!sent) - { - /* - fprintf(stderr, "%c%d\n", VIDEO_SINGLETON::instance ()->frameTable[f].type, f); - fprintf(stderr, "%c frame %d sent.\n", VIDEO_SINGLETON::instance ()->frameTable[f].type, f); - */ - if (VIDEO_SINGLETON::instance ()->frameTable[f].type != 'B') - { - VIDEO_SINGLETON::instance ()->lastRefPtr = 1 - VIDEO_SINGLETON::instance ()->lastRefPtr; - VIDEO_SINGLETON::instance ()->lastRef[VIDEO_SINGLETON::instance ()->lastRefPtr] = f; - } - } - return sent; - } -} - -int -Video_Server::CmdRead (char *buf, int psize) -{ - int res = wait_read_bytes (VIDEO_SINGLETON::instance ()->serviceSocket, - buf, - psize); - if (res == 0) return(1); - if (res == -1) { - fprintf(stderr, "VS error on read VIDEO_SINGLETON::instance ()->cmdSocket, size %d", psize); - perror(""); - return(-1); - } - return 0; -} - -void -Video_Server::CmdWrite(char *buf, int size) -{ - int res = wait_write_bytes(VIDEO_SINGLETON::instance ()->serviceSocket, buf, size); - if (res == -1) { - if (errno != EPIPE) perror("VS writes to VIDEO_SINGLETON::instance ()->serviceSocket"); - exit (errno != EPIPE); - } -} - void Video_Server::on_exit_routine(void) { @@ -758,161 +412,6 @@ Video_Server::on_exit_routine(void) ComCloseConn(VIDEO_SINGLETON::instance ()->videoSocket);*/ } -int -Video_Server::position (void) -{ - int result; - POSITIONpara pos_para; - /* - fprintf(stderr, "POSITION . . .\n"); - */ - result = CmdRead((char *)&pos_para, sizeof(pos_para)); - if (result != 0) - return result; - - if (VIDEO_SINGLETON::instance ()->live_source) return 0; - -#ifdef NeedByteOrderConversion - pos_para.nextGroup = ntohl(pos_para.nextGroup); - pos_para.sn = ntohl(pos_para.sn); -#endif - - CheckGroupRange(pos_para.nextGroup); - VIDEO_SINGLETON::instance ()->cmdsn = pos_para.sn; - result = SendPacket(VIDEO_SINGLETON::instance ()->numS>1 || pos_para.nextGroup == 0, pos_para.nextGroup, 0, 0); - return result; -} - -int -Video_Server::step_video() -{ - int group; - STEPpara step_para; - int tag = 0; - int result; - - result = CmdRead((char *)&step_para, sizeof(step_para)); - if (result != 0) - return result; -#ifdef NeedByteOrderConversion - step_para.sn = ntohl(step_para.sn); - step_para.VIDEO_SINGLETON::instance ()->nextFrame = ntohl(step_para.VIDEO_SINGLETON::instance ()->nextFrame); -#endif - - VIDEO_SINGLETON::instance ()->cmdsn = step_para.sn; - - if (!VIDEO_SINGLETON::instance ()->live_source) { - if (step_para.nextFrame >= VIDEO_SINGLETON::instance ()->numF) /* send SEQ_END */ - { - tag = 1; - step_para.nextFrame --; - } - /* - fprintf(stderr, "STEP . . .frame-%d\n", step_para.VIDEO_SINGLETON::instance ()->nextFrame); - */ - CheckFrameRange(step_para.nextFrame); - group = FrameToGroup(&step_para.nextFrame); - if (VIDEO_SINGLETON::instance ()->precmd != CmdSTEP && !tag ) { - result = SendReferences(group, step_para.nextFrame); - if (result < 0 ) - return result; - } - } - if (VIDEO_SINGLETON::instance ()->live_source) StartPlayLiveVideo(); - - if (VIDEO_SINGLETON::instance ()->live_source) { - SendPicture(&step_para.nextFrame); - } - else if (VIDEO_SINGLETON::instance ()->video_format == VIDEO_MPEG1) { - SendPacket(VIDEO_SINGLETON::instance ()->numS>1, group, tag ? VIDEO_SINGLETON::instance ()->numF : step_para.nextFrame, 0); - } - else { - fprintf(stderr, "VS: wierd1\n"); - } - - if (VIDEO_SINGLETON::instance ()->live_source) StopPlayLiveVideo(); - return 0; -} - -int -Video_Server::init_fast_play (void) -{ - int result; - - result = CmdRead((char *)&VIDEO_SINGLETON::instance ()->fast_para, sizeof(VIDEO_SINGLETON::instance ()->fast_para)); - if (result != 0) - return result; -#ifdef NeedByteOrderConversion - VIDEO_SINGLETON::instance ()->fast_para.sn = ntohl(VIDEO_SINGLETON::instance ()->fast_para.sn); - VIDEO_SINGLETON::instance ()->fast_para.VIDEO_SINGLETON::instance ()->nextGroup = ntohl(VIDEO_SINGLETON::instance ()->fast_para.VIDEO_SINGLETON::instance ()->nextGroup); - VIDEO_SINGLETON::instance ()->fast_para.usecPerFrame = ntohl(VIDEO_SINGLETON::instance ()->fast_para.usecPerFrame); - VIDEO_SINGLETON::instance ()->fast_para.framesPerSecond = ntohl(VIDEO_SINGLETON::instance ()->fast_para.framesPerSecond); - VIDEO_SINGLETON::instance ()->fast_para.VIDEO_SINGLETON::instance ()->VStimeAdvance = ntohl(VIDEO_SINGLETON::instance ()->fast_para.VIDEO_SINGLETON::instance ()->VStimeAdvance); -#endif - - if (VIDEO_SINGLETON::instance ()->live_source) return 0; - - VIDEO_SINGLETON::instance ()->VStimeAdvance = VIDEO_SINGLETON::instance ()->fast_para.VStimeAdvance; - /* - fprintf(stderr, "VIDEO_SINGLETON::instance ()->VStimeAdvance from client: %d\n", VIDEO_SINGLETON::instance ()->VStimeAdvance); - */ - CheckGroupRange(VIDEO_SINGLETON::instance ()->fast_para.nextGroup); - VIDEO_SINGLETON::instance ()->cmdsn = VIDEO_SINGLETON::instance ()->fast_para.sn; - Video_Timer_Global::timerGroup = VIDEO_SINGLETON::instance ()->fast_para.nextGroup; - Video_Timer_Global::timerFrame = 0; - Video_Timer_Global::timerHeader = VIDEO_SINGLETON::instance ()->gopTable[Video_Timer_Global::timerGroup].systemHeader; - VIDEO_SINGLETON::instance ()->currentUPF = VIDEO_SINGLETON::instance ()->fast_para.usecPerFrame; - Video_Timer_Global::StartTimer(); - - fast_play_send (); - return 0; -} - -int -Video_Server::fast_forward (void) -{ - return Video_Server::init_fast_play (); -} - -int -Video_Server::fast_backward (void) -{ - return Video_Server::init_fast_play (); -} - -int -Video_Server::stat_stream(void) -{ - int i, j = 0; - for (i = 0; i < VIDEO_SINGLETON::instance ()->numF; i++) - { - short size = htons(VIDEO_SINGLETON::instance ()->frameTable[i].size); - char type = VIDEO_SINGLETON::instance ()->frameTable[i].type; - if (i == VIDEO_SINGLETON::instance ()->gopTable[j].previousFrames) - { - type = tolower(type); - j ++; - } - CmdWrite((char *)&type, 1); - CmdWrite((char *)&size, 2); - } - return 0; -} - -int -Video_Server::stat_sent(void) -{ -#ifdef STAT - CmdWrite((char *)VIDEO_SINGLETON::instance ()->framesSent, (VIDEO_SINGLETON::instance ()->numF + 7) / 8); -#else - int i; - char zeroByte = 0; - for (i = 0; i < (VIDEO_SINGLETON::instance ()->numF + 7) / 8; i++) - CmdWrite((char *)&zeroByte, 1); -#endif - return 0; -} - // Destructor Video_Server::~Video_Server () { diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.h b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.h index 3ebd6fe9ffa..693990fd776 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.h +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/Video_Server.h @@ -1,5 +1,7 @@ /* -*- C++ -*- */ + + /* $Id$ */ /* Copyright (c) 1995 Oregon Graduate Institute of Science and Technology @@ -41,30 +43,20 @@ #include "proto.h" #include "Video_Control_State.h" -// Function Prototypes -// %% put them in some class maybe ? - -int FBread (char *buf, int size); -int INITvideo (void); -int PLAYliveVideo(PLAYpara * para); -void ComputeFirstSendPattern(float limit); -int FrameToGroup (int * frame); -int SendReferences(int group, int frame); -int send_to_network(int timeToUse); -void StartPlayLiveVideo (void); -void GetFeedBack (void); -int SendPicture (int *frame); -int play_send (int debug=0); -int fast_play_send (void); - class Video_Control_Handler : public virtual ACE_Event_Handler { - + // =TITLE + // Defines the event handler class for the Video Control. + // + // =DESCRIPTION + // This class makes use of a TCP socket.It contains a pointer to + // the current state which is implemented using the state pattern. public: Video_Control_Handler (int video_control_fd); - // Construct this handler with a data fd + // Construct this handler with a control (TCP) fd + // %% use sock stream instead of fd virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE); // Called when input events occur (e.g., connection or data). @@ -88,6 +80,14 @@ private: class Video_Control_Handler_Instance { + // =TITLE + // Defines a Video_Control_Handler_Instance class which is to be + // used as a singleton to give access to a Video_Control_Handler + // instance to the state pattern classes. + // + // =DESCRIPTION + // The Video_Control_Handler has to be set using the + // set_video_control_handler method. public: Video_Control_Handler_Instance (void); @@ -98,11 +98,23 @@ private: Video_Control_Handler *video_control_handler_; }; -typedef ACE_TSS_Singleton <Video_Control_Handler_Instance, ACE_SYNCH_MUTEX> VIDEO_CONTROL_HANDLER_INSTANCE; +typedef ACE_TSS_Singleton <Video_Control_Handler_Instance, + ACE_SYNCH_MUTEX> VIDEO_CONTROL_HANDLER_INSTANCE; +// Video_Control_Handler instance singleton. class Video_Sig_Handler : public virtual ACE_Event_Handler { + // =TITLE + // Defines a video signal handler class which registers itself with the + // default ACE_Reactor::instance () . Handles the + // SIGALRM signal. + // + // =DESCRIPTION + // This class contains a pointer to a Video_Control_Handler + // instance and decides the signal action depending on its state. + // An object of this class is used to periodically send the video + // frames to the client using the Video_Timer_Global class. public: Video_Sig_Handler (Video_Control_Handler *vch); @@ -133,7 +145,14 @@ private: class Video_Data_Handler : public virtual ACE_Event_Handler { - + // =TITLE + // Defines a event handler for video data using a datagram i.e UDP + // socket. + // + // =DESCRIPTION + // This takes a pointer to a Video_Control_Handler instance and + // reacts differently to the events based on the + // video_control_handler's state. public: Video_Data_Handler (int video_data_fd, Video_Control_Handler *vch); @@ -156,15 +175,19 @@ private: }; - - -// %% this class needs a dtor which deletes the -// 3 handlers - data, control, and sig class Video_Server { + // =TITLE + // Defines a class that abstracts the functionality of a + // video_server. + // + // =DESCRIPTION + // This registers 3 event handlers with the ACE_Reactor::instance + // () ,namely a control,data and signal handlers. public: Video_Server (void); // Default constructor + Video_Server (int control_fd, int data_fd, int rttag, @@ -180,30 +203,16 @@ public: int max_pkt_size); // initialize the Video Server. - int run (void); + int register_handlers (void); // register the handlers with the reactor // and set the control_handler to the WAITING state - static int SendPacket (int shtag,int gop,int frame,int timeToUse); - static int CmdRead(char *buf, int psize); - static void CmdWrite(char *buf, int size); static void on_exit_routine(void); - static PLAYpara para; - - static int position (void); - static int step_video (void); - static int fast_forward (void); - static int fast_backward (void); - static int init_play (void); - //static int close (void); - static int stat_stream (void); - static int stat_sent (void); - static int init_fast_play (void); private: ACE_Reactor* reactor_; - // Reactor ,points to ACE_Reactor::instance () + // alias Reactor ,points to ACE_Reactor::instance () Video_Data_Handler* data_handler_; // Data Socket Event Handler diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/vs.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/vs.cpp index 2b05eb569a8..abe2b5b6e69 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/vs.cpp +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_server/vs.cpp @@ -48,6 +48,9 @@ #include "../mpeg_shared/sendpt.h" #include "proto.h" + +// %% Move all these functions to the VIDEO_SINGLETON class and remove +// zombie code like VideoServer ()... static int CmdRead(char *buf, int psize) { int res = wait_read_bytes (VIDEO_SINGLETON::instance ()->serviceSocket, diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.cpp index 2541d5f3fa8..f54dd014169 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.cpp +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.cpp @@ -8,18 +8,18 @@ // called by the acceptor to create a new svc_handler to // handle the new connection. int -Mpeg_Acceptor::make_svc_handler (Mpeg_Svc_Handler *&sh) +AV_Acceptor::make_svc_handler (AV_Svc_Handler *&sh) { ACE_NEW_RETURN (sh, - Mpeg_Svc_Handler (ACE_Reactor::instance (), + AV_Svc_Handler (ACE_Reactor::instance (), this), -1); return 0; } // initialize the svc_handler, and the acceptor. -Mpeg_Svc_Handler::Mpeg_Svc_Handler (ACE_Reactor *reactor, - Mpeg_Acceptor *acceptor) +AV_Svc_Handler::AV_Svc_Handler (ACE_Reactor *reactor, + AV_Acceptor *acceptor) : ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> (0, 0, reactor), acceptor_ (acceptor) @@ -30,7 +30,7 @@ Mpeg_Svc_Handler::Mpeg_Svc_Handler (ACE_Reactor *reactor, // Client connected to our control port // called by the reactor (acceptor) int -Mpeg_Svc_Handler::open (void *) +AV_Svc_Handler::open (void *) { // Lets use threads at a later point. The current scheme works fine @@ -55,7 +55,7 @@ Mpeg_Svc_Handler::open (void *) this->svc (); ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Child returning from Mpeg_Svc_handler::open\n")); + "(%P|%t) Child returning from AV_Svc_handler::open\n")); return 0; default: @@ -63,7 +63,7 @@ Mpeg_Svc_Handler::open (void *) // connections // (1) "this" will commit suicide, because this svc_handler is not required - // in the parent. otherwise, a new mpeg_svc_handler will be created + // in the parent. otherwise, a new AV_Svc_handler will be created // for each connection, and will never go away, i.e. a memory leak // will result. // (2) also, this closes down the "connected socket" in the @@ -73,7 +73,7 @@ Mpeg_Svc_Handler::open (void *) // has a connected socket. this->destroy (); ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Parent Returning from Mpeg_Svc_Handler::open\n")); + "(%P|%t) Parent Returning from AV_Svc_Handler::open\n")); return 0; } return 0; @@ -82,7 +82,7 @@ Mpeg_Svc_Handler::open (void *) // this will handle the connection int -Mpeg_Svc_Handler::svc (void) +AV_Svc_Handler::svc (void) { int result; result = this->handle_connection (); @@ -90,14 +90,14 @@ Mpeg_Svc_Handler::svc (void) if (result != 0) ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Mpeg_Svc_Handler::svc exiting\n")); + "(%P|%t) AV_Svc_Handler::svc exiting\n")); return result; } // handles the connection int -Mpeg_Svc_Handler::handle_connection (ACE_HANDLE) +AV_Svc_Handler::handle_connection (ACE_HANDLE) { int junk; int result; @@ -189,8 +189,8 @@ Mpeg_Svc_Handler::handle_connection (ACE_HANDLE) -INET_SOCKET_BUFFER_SIZE), -1); - // enters the Video_Server run method - result = this->vs_->run (); + // registers the video server handlers. + result = this->vs_->register_handlers (); if (result != 0) ACE_ERROR_RETURN ((LM_ERROR, @@ -219,26 +219,22 @@ Mpeg_Svc_Handler::handle_connection (ACE_HANDLE) } int -Mpeg_Svc_Handler::close (u_long) +AV_Svc_Handler::close (u_long) { - ACE_DEBUG ((LM_DEBUG, "(%P|%t)Mpeg_Svc_Handler::close called \n")); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)AV_Svc_Handler::close called \n")); return 0; } int -Mpeg_Svc_Handler::handle_timeout (const ACE_Time_Value &, +AV_Svc_Handler::handle_timeout (const ACE_Time_Value &, const void *arg) { - ACE_DEBUG ((LM_DEBUG, "(%P|%t)Mpeg_Svc_Handler::handle_timeout called \n")); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)AV_Svc_Handler::handle_timeout called \n")); return 0; } // AV_Server_Sig_Handler routines -// Video_Sig_Handler methods -// handles the timeout SIGALRM signal -// %% this should *not* register itself,but it should -// be registered by the Video_Server::run, alongwith -// the remaining handlers. + AV_Server_Sig_Handler::AV_Server_Sig_Handler (void) { } @@ -266,8 +262,7 @@ AV_Server_Sig_Handler::register_handler (void) // Create a sigset_t corresponding to the signals we want to catch. ACE_Sig_Set sig_set; - // sig_set.sig_add (SIGINT); - // sig_set.sig_add (SIGQUIT); + // handles these signals. sig_set.sig_add (SIGCHLD); sig_set.sig_add (SIGBUS); sig_set.sig_add (SIGINT); @@ -283,8 +278,8 @@ AV_Server_Sig_Handler::register_handler (void) return 0; } -// Called by the ACE_Reactor to extract the fd. +// Called by the ACE_Reactor to extract the fd. ACE_HANDLE AV_Server_Sig_Handler::get_handle (void) const { @@ -323,13 +318,18 @@ AV_Server_Sig_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *) switch (signum) { case SIGCHLD: - // Handle the timeout - AV_Server::clear_child (SIGCHLD); + // Handle the death of child signal. + this->clear_child (SIGCHLD); break; case SIGBUS: + // Handle the Bus error signal case SIGINT: + // Handle the interrupt signal case SIGTERM: - AV_Server::int_handler (signum); + // Handle the process termination signal. + this->int_handler (signum); + break; + default: ACE_DEBUG ((LM_DEBUG, "(%t) %S: not handled, returning to program\n", signum)); @@ -338,47 +338,9 @@ AV_Server_Sig_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *) return 0; } - -// AV_Server routines - -// Default Constructor -AV_Server::AV_Server () -{ - this->sh_ = new AV_Server_Sig_Handler ; -} - -// Cluttering the code with various signal handlers here. - -// ctrl-c handler,Bus error handler,interrupt sig handler -void -AV_Server::int_handler (int sig) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) killed by signal %d", - sig)); - exit (0); -} - -void -AV_Server::on_exit_routine (void) -{ - // %% what does the following do - if (Mpeg_Global::parentpid != ACE_OS::getpid ()) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Process is exiting\n")); - return; - } - - // %% what does the following do - if (Mpeg_Global::live_audio > 1) ExitLiveAudio (); - if (Mpeg_Global::live_video > 1) ExitLiveVideo (); - // ComCloseServer(); -} - // SIGCHLD handler void -AV_Server::clear_child (int sig) +AV_Server_Sig_Handler::clear_child (int sig) { int pid; int status; @@ -426,6 +388,43 @@ AV_Server::clear_child (int sig) } } +// ctrl-c, Bus error, interrupt sig handler +void +AV_Server_Sig_Handler::int_handler (int sig) +{ + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) killed by signal %d", + sig)); + exit (0); +} + +// AV_Server routines + +// Default Constructor +AV_Server::AV_Server () +{ + this->signal_handler_ = new AV_Server_Sig_Handler ; +} + +// %% move to the destructor or sig handler +void +AV_Server::on_exit_routine (void) +{ + // %% what does the following do + if (Mpeg_Global::parentpid != ACE_OS::getpid ()) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) Process is exiting\n")); + return; + } + + // %% what does the following do + if (Mpeg_Global::live_audio > 1) ExitLiveAudio (); + if (Mpeg_Global::live_video > 1) ExitLiveVideo (); + // ComCloseServer(); +} + + // Parses the command line arguments int AV_Server::parse_args (int argc, @@ -468,19 +467,6 @@ AV_Server::parse_args (int argc, return 0; } -// sets the handlers for the various signals -int -AV_Server::set_signals () -{ - setsignal (SIGCHLD, clear_child); - setsignal (SIGPIPE, SIG_IGN); - setsignal (SIGBUS, int_handler); - setsignal (SIGINT, int_handler); - setsignal (SIGTERM, int_handler); - // setsignal(SIGALRM, SIG_IGN); - return 0; -} - // Initializes the mpeg server int @@ -493,10 +479,8 @@ AV_Server::init (int argc, if (result < 0) return result; - // This code has become obsolete with the new AV_Server_Sig_Handler class.. - // this->set_signals (); // Register the various signal handlers with the reactor. - result = this->sh_->register_handler (); + result = this->signal_handler_->register_handler (); if (result < 0) return result; @@ -504,7 +488,8 @@ AV_Server::init (int argc, Mpeg_Global::parentpid = ACE_OS::getpid (); ::atexit (on_exit_routine); - + + // %% if (Mpeg_Global::live_audio) { if (InitLiveAudio (argc, argv) == -1) @@ -564,8 +549,8 @@ AV_Server::run () AV_Server::~AV_Server (void) { - if (this->sh_ != 0) - delete this->sh_; + if (this->signal_handler_ != 0) + delete this->signal_handler_; } int diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.h b/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.h index 49740df3c1e..411767c6347 100644 --- a/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.h +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/server/server.h @@ -1,5 +1,21 @@ /* -*- c++ -*- */ +/* $Id$ */ + +// ============================================================================ +// +// = LIBRARY +// server +// +// = FILENAME +// server.h +// +// = AUTHORS +// Sumedh Mungee (sumedh@cs.wustl.edu) +// Nagarajan Surendran (naga@cs.wustl.edu) +// +// ============================================================================ + #if !defined (TAO_AV_SERVER_H) #define TAO_AV_SERVER_H @@ -38,26 +54,40 @@ #include "../mpeg_server/Video_Server.h" -class Mpeg_Svc_Handler; +class AV_Svc_Handler; -class Mpeg_Acceptor - : public virtual ACE_Acceptor <Mpeg_Svc_Handler, +class AV_Acceptor + : public virtual ACE_Acceptor <AV_Svc_Handler, ACE_SOCK_ACCEPTOR> { + // =TITLE + // This defines a AV_Acceptor which is an Acceptor and + // overrides the make_svc_handler method of the Acceptor. + // + // =DESCRIPTION + // This class overrides the Acceptor's make_svc_handler so that a + // AV_Svc_Handler can be created with a non-default constructor. public: - virtual int make_svc_handler (Mpeg_Svc_Handler *&sh); - // Initialize the <Mpeg_Svc_Handler>. + virtual int make_svc_handler (AV_Svc_Handler *&sh); + // Create a new <AV_Svc_Handler> passing 'this' to the service handler }; -class Mpeg_Svc_Handler +class AV_Svc_Handler : public virtual ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> { - // @@ Naga, please make sure to document all these classes with the =TITLE/=DESCRIPTION stuff! + // =TITLE + // This class defines the service handler for a new connection to + // the AV_Server. + // + // =DESCRIPTION + // This calls the handle_connection method for a new connection + // which demuxes the connection to a video or audio server depending + // on the connection request. public: // = Initialization method. - Mpeg_Svc_Handler (ACE_Reactor * = 0, - Mpeg_Acceptor * = 0); + AV_Svc_Handler (ACE_Reactor * = 0, + AV_Acceptor * = 0); virtual int open (void *); // Perform the work of the SVC_HANDLER. Called by the acceptor @@ -72,8 +102,10 @@ public: virtual int close (u_long); // Called if ACE_Svc_Handler is closed down unexpectedly. - virtual int handle_timeout (const ACE_Time_Value &, const void *arg); - // Handles acceptor timeouts. + int handle_timeout (const ACE_Time_Value &, + const void *arg); + // handle the timeout + private: ACE_SOCK_CODgram dgram_; @@ -85,7 +117,7 @@ private: ACE_INET_Addr client_data_addr_; // Data (UDP) Address of the client. - Mpeg_Acceptor *acceptor_; + AV_Acceptor *acceptor_; // Pointer to the Acceptor that created us so that we can remove it // from the <ACE_Reactor> when we <fork>. @@ -103,28 +135,43 @@ public: int register_handler (void); // this will register this sig_handler - // with the reactor + // with the reactor for SIGCHLD,SIGTERM,SIGINT virtual int shutdown (ACE_HANDLE, ACE_Reactor_Mask); virtual int handle_input (ACE_HANDLE); + // handle input on the dummy handle. virtual int handle_signal (ACE_HANDLE signum, siginfo_t * = 0, ucontext_t* = 0); + // handles the SIGCHLD,SIGTERM,SIGINT for the parent process i.e + // the main thread.. + + void int_handler (int sig); + // Signal handler function for SIGTERM,SIGBUS,SIGINT + + void clear_child (int sig); + // Signal handler function for SIGCHLD private: ACE_HANDLE handle_; + // dummy handle for the sig handler. }; class AV_Server { // =TITLE - // Defines a class that abstracts the functionality of a mpeg + // Defines a class that abstracts the functionality of a // video and audio server. + // =DESCRIPTION + // Using the class is as simple as calling init () first and then + // run. It uses an acceptor with the default ACE_Reactor::instance (). public: AV_Server (); + // constructor + int init (int argc, char **argv); // Initialize the AV_Server @@ -132,20 +179,17 @@ public: int run (); // Run the AV_Server - static void int_handler (int sig); - static void on_exit_routine (void); - static void clear_child (int sig); - // various signal handlers - // we need them to be static - static void init_static (void); + static void on_exit_routine (void); + // Routine called when this process exits. ~AV_Server (); + // Destructor private: - Mpeg_Acceptor acceptor_; + AV_Acceptor acceptor_; // the acceptor - AV_Server_Sig_Handler *sh_; + AV_Server_Sig_Handler *signal_handler_; // Signal handler for SIGCHLD,SIGINT,SIGTERM,SIGBUS ACE_INET_Addr server_control_addr_; @@ -155,8 +199,6 @@ private: char **argv); // parse the arguments - int set_signals (void); - }; #endif // TAO_AV_SERVER_H |