📄 main.c
字号:
/*
* GPAC - Multimedia Framework C SDK
*
* Copyright (c) Cyril Concolato / Jean Le Feuvre 2000-2005
* All rights reserved
*
* This file is part of GPAC / mp4 simple streamer application
*
* GPAC is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* GPAC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
//------------------------------------------------------------
// Includes
//------------------------------------------------------------
// Third
// Project
#include <gpac/constants.h>
#include <gpac/isomedia.h>
#include <gpac/ietf.h>
#include <gpac/internal/ietf_dev.h>
#include <gpac/config.h>
#include <gpac/thread.h>
//------------------------------------------------------------
// Define
//------------------------------------------------------------
#define PATHFILE "."
#define RTP_HEADER_SIZE 12 // in bytes (octets)
//------------------------------------------------------------
// Declaration of static variables
//------------------------------------------------------------
u32 sov_numberBurstSent = 0; // toutes sessions confondues
u32 sov_timeOffset = 0; // time when the first burts was sent. this time <=> (CTS=0)
//------------------------------------------------------------
// Typedef
//------------------------------------------------------------
typedef struct {
// config
u32 sov_burstDuration;
u32 sov_peakBitRate;
u32 sov_delay_offtime;
u32 sov_nbSessions;
char * sop_ip; // destination ip
u32 *sop_portTable; // port of each session
char **sop_fileTable; // filename of each session
u32 *sop_trackNbTable; // track id of each session
u32 *sop_looping; // 1 play in a loop, 0 play once
// time
u32 ov_currentTime;
u32 ov_timeOrigin; // origin of main.c ( = 0)
// other param
u32 sov_numberPacketSent;
u32 sov_burstSize;
} Simulator;
typedef struct {
GF_RTPHeader header;
char *payload;
u32 payload_len;
} RTP_Packet;
typedef struct {
/* id */
int id;
u32 bitRate; // of the media
u32 mediaSize;
u32 mediaDuration;
u32 nbAccesUnit;
u32 maxSizeBurst; // max size to fill the burst with the media bitRate
u32 physicalBitRate; // cf definition in checkConfiguration
u32 looping; // 1: play the media in a loop, 0 play once
/* access unit*/
u32 accessUnitProcess; // number of the AU to process. set to 0 at the beginnning
u32 nextBurstTime;
u32 dataLengthInBurst; // total length filled in current burst
u64 totalLengthSent; // total length sent to channel
/* Type */
GF_RTPChannel *channel;
GP_RTPPacketizer *packetizer;
GF_List *packets_to_send;
GF_ISOSample *accessUnit; // the AU
GF_ISOFile *mp4File;
/* The current packet being formed */
GF_RTPHeader header;
char *payload;
u32 payload_len;
u32 payload_valid_len;
/* Management */
Simulator *global;
GF_Thread *thread; // thread of session 1 is not used
} RTP_Caller;
//------------------------------------------------------------
//
// Functions
//
//------------------------------------------------------------
/*
* setOffsetTime
* sets the offset time, ie the time when the very first burst was sent
* ==> allows to syncrhonise the CTS time unit to the system time
*/
void setOffsetTime(u32 av_offsetTime)
{
sov_timeOffset = av_offsetTime;
}
/*
* initTimeManagement
* is called when the first burst of the session 1 is sent
* sets the nextBurstTime
* -> session 1: offset + offTime
* -> other: offset + (id -1) * offTime
*/
void initTimeManagement(RTP_Caller *ap_caller)
{ // set the time when CTS = 0
if(ap_caller->id == 1)
{
ap_caller->nextBurstTime = sov_timeOffset +ap_caller->global->sov_burstDuration + ap_caller->global->sov_delay_offtime;
}
else
{
ap_caller->nextBurstTime = sov_timeOffset + (ap_caller->id - 1)* ap_caller->global->sov_burstDuration;
}
//fprintf(stdout,"mp4 streamer: [initMgtTime] _id %u _currentTime %u _nextBurstTime %u\n",ap_caller->id, gf_sys_clock(),ap_caller->nextBurstTime);
}
/*
* setNextBurstTime
* is called in OnPacketDone just before the burst is sent
* sets the nextBurstTime of the given session
*/
void setNextBurstTime(RTP_Caller *ap_caller)
{
ap_caller->nextBurstTime = gf_sys_clock() + ap_caller->global->sov_burstDuration + ap_caller->global->sov_delay_offtime;
//fprintf(stdout,"mp4 streamer: [setNextBurstTime] _id %u _currentTime %u _nextBurstTime %u\n",ap_caller->id, gf_sys_clock(),ap_caller->nextBurstTime);
}
/*
* callback functions
*
*
*/
static void OnNewPacket(void *cbk, GF_RTPHeader *header)
{
RTP_Caller *caller = cbk;
if (!header) return;
memcpy(&caller->header, header, sizeof(GF_RTPHeader));
//fprintf(stdout, "mp4 streamer: [ONP] _session %u\n", caller->id);
} /* OnNewPacket */
static void OnPacketDone(void *cbk, GF_RTPHeader *header)
{
RTP_Caller *caller = cbk;
u32 lv_nextBurstTime; // date du prochain envoie du burst normalement
u32 lv_sizeSent; // taille totale des paquets envoy閟 pour le burst courant (bits)
lv_sizeSent = 0;
lv_nextBurstTime = caller->nextBurstTime; // time of next burst to play
caller->global->ov_currentTime = gf_sys_clock();// gets system clock (current time)
//fprintf(stdout,"[OPD] _id %u _AU %u _currentTime %u _nextBursTime %u\n",caller->id, caller->accessUnitProcess, caller->global->ov_currentTime, lv_nextBurstTime);
/*
* Check for the first burst sending
* ==> allows to set the time of the first sending and start threads
*
*/
if(sov_numberBurstSent == 0 && (caller->id == 1))
{
u32 lv_totalLengthFilled =0; // in bits
u32 i;
u32 lv_packetCount=0;
u32 lv_currentPacketSize; // in bits
RTP_Packet *tmp;
GF_SAFEALLOC(tmp, sizeof(RTP_Packet));
memcpy(&tmp->header, header, sizeof(GF_RTPHeader));
tmp->payload = caller->payload;
caller->payload = NULL;
tmp->payload_len = caller->payload_len;
caller->payload_len = 0;
caller->payload_valid_len = 0;
lv_packetCount = gf_list_count(caller->packets_to_send);
lv_currentPacketSize = (tmp->payload_len + RTP_HEADER_SIZE) * 8; // in bits
if(lv_packetCount == 0)
{
lv_totalLengthFilled += lv_currentPacketSize;
}
else
{
for (i=0;i< lv_packetCount;i++)
{
RTP_Packet *lp_buffer;
lp_buffer = gf_list_get(caller->packets_to_send, i);
lv_totalLengthFilled += (lp_buffer->payload_len + RTP_HEADER_SIZE) * 8;
}
lv_totalLengthFilled += lv_currentPacketSize;
}
if( lv_totalLengthFilled >= caller->maxSizeBurst )
{ // send the RTP packets in gf_list
setOffsetTime(caller->global->ov_currentTime ); /* SPECIFIC TO THE FIRST SESSION */
if(lv_packetCount == 0) // hardly ever happens...
{
caller->totalLengthSent += (tmp->payload_len * 8);
gf_rtp_send_packet(caller->channel, &tmp->header, 0, 0, tmp->payload, tmp->payload_len);
free(tmp->payload);
}
else
{
for (i=0;i<= lv_packetCount -1 ;i++)
{
RTP_Packet *rtp = gf_list_get(caller->packets_to_send, i);
caller->totalLengthSent += (rtp->payload_len * 8) ; // update the total length
gf_rtp_send_packet(caller->channel, &rtp->header, 0, 0, rtp->payload, rtp->payload_len);
free(rtp->payload);
}
gf_list_reset(caller->packets_to_send);
}
sov_numberBurstSent++;
fprintf(stdout, "[OPD SEN] 1st burstSent _pktSize %u _totSize %u _nbBurstSent %u _offtime %u\n", lv_currentPacketSize, lv_totalLengthFilled, sov_numberBurstSent, gf_sys_clock() );
} // end if
else // store
{
//fprintf(stdout, "[OPD STO] 1st rtp store _pktSize %u _totSize %u\n", lv_currentPacketSize, lv_totalLengthFilled);
}
gf_list_add(caller->packets_to_send, tmp); // store the last packet not sent
} // end if first packet of session n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -