⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 media-app.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 4 页
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *///// Copyright (c) 1997 by the University of Southern California// All rights reserved.//// Permission to use, copy, modify, and distribute this software and its// documentation in source and binary forms for non-commercial purposes// and without fee is hereby granted, provided that the above copyright// notice appear in all copies and that both the copyright notice and// this permission notice appear in supporting documentation. and that// any documentation, advertising materials, and other materials related// to such distribution and use acknowledge that the software was// developed by the University of Southern California, Information// Sciences Institute.  The name of the University may not be used to// endorse or promote products derived from this software without// specific prior written permission.//// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about// the suitability of this software for any purpose.  THIS SOFTWARE IS// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// Other copyrights might apply to parts of this software and are so// noted when applicable.//// Implementation of media application//// $Header: /nfs/jade/vint/CVSROOT/ns-2/rap/media-app.cc,v 1.12 1999/11/18 23:14:31 haoboy Exp $#include <stdarg.h>#include "template.h"#include "media-app.h"#include "utilities.h"//----------------------------------------------------------------------// Classes related to a multimedia object//// MediaSegment// MediaSegmentList: segments in a layer// MediaPage: a stored multimedia object (stream)//----------------------------------------------------------------------MediaSegment::MediaSegment(const HttpMediaData& d) : flags_(0){	start_ = d.st();	end_ = d.et();	if (d.is_last())		set_last();	if (d.is_pref())		set_pref();}void MediaSegmentList::add(const MediaSegment& s) {	MediaSegment* tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->before(s))) {		tmp = tmp->next();	}	// Append at the tail, or the first element in list	if (tmp == NULL) {		length_ += s.datasize();		if ((tail_ != NULL) && ((MediaSegment *)tail_)->overlap(s)) 			// Don't need to merge because it's merged at the end			((MediaSegment*)tail_)->merge(s);		else {			MediaSegment *p = new MediaSegment(s);			if (head_ == NULL)				head_ = tail_ = p;			else 				append(p, tail_);		}		if (getsize() != length_) {			fprintf(stderr, 				"MediaSegmentList corrupted: Point 1.\n");			abort();		}		return;	}	// Update total stored length ONLY IF s is not in tmp.	if (tmp->in(s)) {		fprintf(stderr, 			"MediaSegmentList: get a seg (%d %d) which is already in cache!\n",			s.start(), s.end());		fprintf(stderr, "List contents: ");		print();#if 1		//Tcl::instance().eval("[Test instance] flush-trace");		//abort();#endif		// XXX Don't abort, simply continue		return;	}	// Insert a MediaSegment into list. Note: Don't do merge!	if (tmp->overlap(s)) {		length_ += (s.datasize() - tmp->merge(s));	} else {		MediaSegment *p = new MediaSegment(s);		insert(p, tmp);		tmp = p;		length_ += s.datasize();	}	if (getsize() != length_) {		fprintf(stderr, "MediaSegmentList corrupted: Point 2.\n");		abort();	}	merge_seg(tmp);	if (getsize() != length_) {		fprintf(stderr, "MediaSegmentList corrupted: Point 3.\n");		abort();	}}void MediaSegmentList::merge_seg(MediaSegment* tmp){	// See if <tmp> can be merged with next segments	MediaSegment *q = tmp->next();	while (q && q->overlap(*tmp)) {#if 1		if ((tmp->start() == q->start()) && (tmp->end() == q->end())) {			abort();		}#endif		tmp->merge(*q);		detach(q);		delete q;		q = tmp->next();	}	// See if <tmp> can be merged with previous segments	q = tmp->prev();	while (q && q->overlap(*tmp)) {		tmp->merge(*q);		assert(tail_ != q);		detach(q);		delete q;		q = tmp->prev();	}}int MediaSegmentList::in(const MediaSegment& s){	MediaSegment* tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->before(s)))		tmp = tmp->next();	// If all segments are before s, or the first segment which isn't 	// before s doesn't overlap with s, s isn't in this list.	if ((tmp == NULL) || !s.in(*tmp))		return 0;	else 		return 1;}// Get the next segment which is not before 's', but with the same size// as the given 's'. This segment may not overlap with s. MediaSegment MediaSegmentList::get_nextseg(const MediaSegment& s) {	MediaSegment res(0, 0); // If unsuccessful, return start() = 0	MediaSegment* tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->before(s))) 		tmp = tmp->next();	if (tmp == NULL) {		res.set_last();		return res;	}	assert(tmp->end() > s.start());// 	// Don't return a segment which do not *OVERLAP* with s // 	// (boundary overlap is excluded).// 	if ((tmp->end() <= s.start()) || (tmp->start() >= s.end())) // 	    return res;	// XXX How to flag that no more data is available in the future??	res = s;	int orig_size = s.datasize();	if (res.start() < tmp->start()) {		// |-------| (s)    ---> time axis		//    |--------| (tmp)		//		// The start time of s is invalid, we need to adjust both 		// the start time (and size if necessary)		res.set_start(tmp->start());		if (tmp->datasize() < orig_size) 			// Not enough data available??			res.set_datasize(tmp->datasize());		else			res.set_datasize(orig_size);	} else if (res.end() > tmp->end()) {		//    |---------| (s)    ---> time axis		// |-------| (tmp)		// 		// The start time in s is valid, but we may need to adjust the 		// end time (i.e., size) of s.		res.set_datasize(tmp->end()-res.start());	}	// Falling through means that the requested segment is available 	// and can be returned as it is.	assert(res.datasize() <= tmp->datasize());	if ((res.end() == tmp->end()) && (tmp->next() == NULL))		// This is the last data segment of the layer		res.set_last();	return res;}// Note that evicting all segments in this layer may not leave enough // space, so we return the number of bytes evicted from this layerint MediaSegmentList::evict_tail(int size){	int sz = size, tz;	MediaSegment *tmp = (MediaSegment *)tail_;	while ((tmp != NULL) && (sz > 0)) {		// Reduce the last segment's size and adjust its playout time		tz = tmp->evict_tail(sz);		length_ -= tz;		sz -= tz; 		if (tmp->datasize() == 0) {			// This segment is empty now			detach(tmp);			delete tmp;			tmp = (MediaSegment *)tail_;		}	}	return size - sz;}// Evicting <size> from the head of the listint MediaSegmentList::evict_head(int size){	int sz = size, tz;	MediaSegment *tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (sz > 0)) {		// Reduce the last segment's size and adjust its playout time		tz = tmp->evict_head(sz);		sz -= tz; 		length_ -= tz;		if (tmp->datasize() == 0) {			// This segment is empty now			detach(tmp);			delete tmp;			tmp = (MediaSegment *)head_;		}	}	return size - sz;}// Evict all segments before <offset> from head and returns the size of // evicted segments.int MediaSegmentList::evict_head_offset(int offset){	int sz = 0;	MediaSegment *tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->start() < offset)) {		if (tmp->end() <= offset) {			// delete whole segment			sz += tmp->datasize();			length_ -= tmp->datasize();			detach(tmp);			delete tmp;			tmp = (MediaSegment *)head_;		} else {			// remove part of the segment			sz += offset - tmp->start();			length_ -= offset - tmp->start();			tmp->set_start(offset);		}	}	if (head_ == NULL)		tail_ = NULL;	return sz;}// Return a list of "holes" between the given offsetsMediaSegmentList MediaSegmentList::check_holes(const MediaSegment& s){	MediaSegmentList res;  // empty list	MediaSegment* tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->before(s)))		tmp = tmp->next();	// If all segments are before s, s is a hole	if (tmp == NULL) {		res.add(s);		return res;	}	// If s is within *tmp, there is no hole	if (s.in(*tmp))		return res;	// Otherwise return a list of holes	int soff, eoff;	soff = s.start();	eoff = s.end();	while ((tmp != NULL) && (tmp->overlap(s))) {		if (soff < tmp->start()) {			// Only refetches the missing part			res.add(MediaSegment(soff, min(eoff, tmp->start())));#if 1			// DEBUG ONLY			// Check if these holes are really holes!			if (in(MediaSegment(soff, min(eoff, tmp->start())))) {				fprintf(stderr, "Wrong hole: (%d %d) ", 					soff, min(eoff, tmp->start()));				fprintf(stderr, "tmp(%d %d), s(%d %d)\n",					tmp->start(), tmp->end(),					soff, eoff);				fprintf(stderr, "List content: ");				print();			}#endif		}		soff = tmp->end();		tmp = tmp->next();	}	if (soff < eoff) {		res.add(MediaSegment(soff, eoff));#if 1				// DEBUG ONLY		// Check if these holes are really holes!		if (in(MediaSegment(soff, eoff))) {			fprintf(stderr, "Wrong hole #2: (%d %d)\n", 				soff, eoff);			fprintf(stderr, "List content: ");			print();		}#endif	}#if 0	check_integrity();#endif	return res;}void MediaSegmentList::check_integrity(){	MediaSegment *p, *q;	p = (MediaSegment*)head_;	while (p != NULL) {		q = p; 		p = p->next();		if (p == NULL)			break;		if (!q->before(*p)) {			fprintf(stderr, 				"Invalid segment added: (%d %d), (%d %d)\n", 				q->start(), q->end(), p->start(), p->end());			abort();		}	}}// Return the portion in s that is overlap with any segments in this list// Sort of complementary to check_holes(), but it does not return a list, // hence smaller overhead. int MediaSegmentList::overlap_size(const MediaSegment& s) const{	int res = 0;	MediaSegment* tmp = (MediaSegment *)head_;	while ((tmp != NULL) && (tmp->before(s)))		tmp = tmp->next();	// If all segments are before s, there's no overlap	if (tmp == NULL)		return 0;	// If s is within *tmp, entire s overlaps with the list	if (s.in(*tmp))		return s.datasize();	// Otherwise adds all overlapping parts together.	int soff, eoff;	soff = s.start();	eoff = s.end();	while ((tmp != NULL) && (tmp->overlap(s))) {		res += min(eoff, tmp->end()) - max(soff, tmp->start());		soff = tmp->end();		tmp = tmp->next();	}	return res;}// Debug onlyvoid MediaSegmentList::print() {	MediaSegment *p = (MediaSegment *)head_;	int i = 0, sz = 0;	while (p != NULL) {		printf("(%d, %d)  ", p->start(), p->end());		sz += p->datasize();		p = p->next();		if (++i % 8 == 0)			printf("\n");	}	printf("\nTotal = %d\n", sz);}// Debug onlyint MediaSegmentList::getsize(){	MediaSegment *p = (MediaSegment *)head_;	int sz = 0;	while (p != NULL) {		sz += p->datasize();		p = p->next();	}	return sz;}// Print into a char array with a given size. Abort if the size is exceeded.char* MediaSegmentList::dump2buf(){	char *buf = new char[1024];	char *b = buf;	MediaSegment *p = (MediaSegment *)head_;	int i = 0, sz = 1024;	buf[0] = 0;	while (p != NULL) {		// XXX snprintf() should either be in libc or implemented		// by TclCL (see Tcl2.cc there).		i = snprintf(b, sz, "{%d %d} ", p->start(), p->end());		sz -= i;		// Boundary check: if less than 50 bytes, allocate new buf		if (sz < 50) {			char *tmp = new char[strlen(buf)+1024];			strcpy(tmp, buf);			delete []buf;			buf = tmp;			b = buf + strlen(buf);			sz += 1024;		} else 			b += i;		p = p->next();	}	return buf;}HttpMediaData::HttpMediaData(const char* sender, const char* page, int layer, 			     int st, int et) :	HttpData(MEDIA_DATA, 0), layer_(layer), st_(st), et_(et), flags_(0){	assert(strlen(page)+1 <= (size_t)HTTP_MAXURLLEN);	strcpy(page_, page);	assert(strlen(sender)+1 <= (size_t)HTTP_MAXURLLEN);	strcpy(sender_, sender);}static class MappClass : public TclClass {public:	MappClass() : TclClass("Application/MediaApp") {}	TclObject* create(int argc, const char*const* argv) {		if (argc > 4) 			return (new MediaApp(argv[4]));		return NULL;	}} class_mapp;MediaApp::MediaApp(const char* page) : 	log_(0), num_layer_(0), last_layer_(0){	strcpy(page_, page);	// Initialize all layer data pointers	for (int i = 0; i < MAX_LAYER; i++)		data_[i].set_start(0); 	bind("segmentSize_", &seg_size_);}void MediaApp::start(){ 	fprintf(stderr, "MediaApp::start() not supported\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -