<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<META content="MSHTML 5.00.3315.2870" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT size=2>Hi:</FONT></DIV>
<DIV><FONT size=2> I am a uviertity student wants make a network mp3
player with sdl-sound.</FONT></DIV>
<DIV><FONT size=2>I start a thread of rtp to reciever rtp packet from network
interface,and start a thread to decode(mp3) and playback the audio.</FONT><FONT
size=2>I add the rtp-packet to a queue and decode it to
a big buffer.Now the audio can be played but play 3 second then stop
,I think the</FONT></DIV>
<DIV><FONT size=2>callback function of sdl audio confuse me.</FONT></DIV>
<DIV><FONT size=2> Need I start a new thread to prepare the big size
buffer ,and is the callback function return after play all the data in the big
size buffer.</FONT></DIV>
<DIV><FONT size=2> here is my program:</FONT></DIV>
<DIV><FONT size=2><BR>#include "lame.h"<BR>#include
<sys/timeb.h></FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>#include <ctype.h></FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>#include <stdio.h><BR>#include
<stdlib.h><BR>#include <string.h></FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR>#include "debug.h"<BR>#include "memory.h"<BR>#include
"rtp.h"<BR>#include "SDL.h"<BR>#include "SDL_audio.h"<BR>#include
"SDL_thread.h"<BR>#define MAXSIZE 44100*5</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>#ifdef WIN32<BR>#define WS_VERSION_ONE
MAKEWORD(1,1)<BR>#define WS_VERSION_TWO MAKEWORD(2,2)<BR>#endif</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>#define MAXPCM 44100*5<BR>typedef struct
pcm_data<BR>{<BR> uint8_t * data;<BR> uint32_t
data_len;<BR> struct pcm_data * next;<BR>}
PCM_DATA_T;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/******************global
variable**********************/<BR> PCM_DATA_T
header={NULL,0,NULL};<BR> PCM_DATA_T *current;<BR> struct rtp *
session;<BR> SDL_mutex *mutex = NULL;<BR> static SDL_sem
*sem;<BR> uint8_t *sound; /* Pointer to wave
data */<BR> uint32_t soundlen; /* Length of wave
data */<BR> int soundpos; /*
Current play position */<BR> uint8_t pcmBuffer[MAXPCM];<BR>
<BR>/******************************************************/<BR>static void
<BR>usage() <BR>{<BR> printf("Usage: rtpdemo [switches] address
port\n");<BR> printf("Valid switches are:\n");<BR> printf("
-f\t\tFilter local packets out of receive stream.");<BR> printf("
-l\t\tListen and do not transmit data.\n");<BR> exit(-1);<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2></FONT> </DIV>
<DIV> </DIV>
<DIV><FONT size=2>/*
-------------------------------------------------------------------------
*/<BR>/* RTP callback related */</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static void<BR>sdes_print(struct rtp *session, uint32_t ssrc,
rtcp_sdes_type stype) {<BR> const char *sdes_type_names[] =
{<BR> "end", "cname", "name", "email", "telephone",
<BR> "location", "tool", "note", "priv"<BR> };<BR> const
uint8_t n = sizeof(sdes_type_names) / sizeof(sdes_type_names[0]);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (stype > n) {<BR> /* Theoretically
impossible */<BR> printf("boo! invalud sdes field %d\n",
stype);<BR> return;<BR> }<BR> <BR> printf("SSRC 0x%08x
reported SDES type %s - ", ssrc, <BR>
sdes_type_names[stype]);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (stype == RTCP_SDES_PRIV) {<BR> /*
Requires extra-handling, not important for example
*/<BR> printf("don't know how to display.\n");<BR> } else
{<BR> printf("%s\n", rtp_get_sdes(session, ssrc,
stype));<BR> }<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static void<BR>addtoQueue(struct rtp *session, rtp_packet *p)
<BR>{<BR>static uint32_t counter=0;<BR>uint16_t
pcmBuffer[2][1152];<BR>PCM_DATA_T *temp=&header;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>PCM_DATA_T * tempPacket=(PCM_DATA_T
*)malloc(sizeof(PCM_DATA_T));/*when use the data,remeber to free the queue
packet and xfree the rtp*/<BR>if(tempPacket==NULL)<BR>{<BR> printf("no
enough memory left");<BR> exit(-1);<BR>}<BR>printf("Received data
(payload=%d timestamp=%06d size=%06d) ", p->rtp_pak_pt, p->rtp_pak_ts,
p->rtp_data_len);<BR>/*begin decode*/<BR> <BR> <BR>/*end
decode*/<BR>SDL_mutexP(mutex);<BR>tempPacket->data=(uint8_t
*)malloc(p->rtp_data_len);<BR>tempPacket->next
=NULL;<BR>memcpy(tempPacket->data,p->rtp_data,p->rtp_data_len);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT
size=2>tempPacket->data_len=p->rtp_data_len;<BR>tempPacket->next=NULL;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>while(temp->next!=NULL)//find the last
<BR> {temp=temp->next;<BR> }<BR>temp->next=tempPacket;<BR>SDL_mutexV(mutex);<BR>SDL_SemPost(sem);<BR>printf("I
get %d packet\n",counter++);<BR>printf("the current value is %d
\n",SDL_SemValue(sem));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (p->rtp_pak_ssrc == rtp_my_ssrc(session))
{<BR> /* Unless filtering is enabled we are likely to
see<BR> out packets if sending to a multicast group.
*/<BR> printf("that I just sent.\n");<BR> } else
{<BR> printf("from SSRC 0x%08x\n", p->rtp_pak_ssrc); <BR> }
<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static void<BR>rtp_event_handler(struct rtp *session,
rtp_event *e)
<BR>{<BR> rtp_packet *p;<BR> rtcp_sdes_item *r;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> switch(e->type) {<BR> case RX_RTP:
<BR> p =
(rtp_packet*)e->data;<BR> addtoQueue(session,
p);<BR> xfree(p); /* xfree() is mandatory to release RTP packet data
*/<BR> break;<BR> case RX_SDES:<BR> r =
(rtcp_sdes_item*)e->data;<BR> sdes_print(session, e->ssrc,
r->type);<BR> break;<BR> case
RX_BYE:<BR> break;<BR> case
SOURCE_CREATED:<BR> printf("New source created, SSRC = 0x%08x\n",
e->ssrc);<BR> break;<BR> case
SOURCE_DELETED:<BR> printf("Source deleted, SSRC = 0x%08x\n",
e->ssrc);<BR> break;<BR> case RX_SR:<BR> case
RX_RR:<BR> case RX_RR_EMPTY:<BR> case RX_RTCP_START:<BR> case
RX_RTCP_FINISH:<BR> case RR_TIMEOUT:<BR> case
RX_APP:<BR>; }<BR> fflush(stdout);<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/*
-------------------------------------------------------------------------
*/<BR>/* Send and receive loop. Sender use 20ms audio mulaw packets
*/</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>#define MULAW_BYTES 4 * 160<BR>#define
MULAW_PAYLOAD 0<BR>#define MULAW_MS 4 * 20</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2></FONT> </DIV>
<DIV> </DIV>
<DIV><FONT size=2>static void<BR>recieve_packet(struct rtp* session, int
send_enable) <BR>{<BR> struct timeval timeout;<BR> uint32_t
rtp_ts;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (send_enable) {<BR> printf("Sending and
listening to ");<BR> } else {<BR> printf("Listening to
");<BR> }<BR> printf("%s port %d (local SSRC = 0x%08x)\n",
<BR> rtp_get_addr(session),
<BR>
rtp_get_rx_port(session),<BR>
rtp_my_ssrc(session));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2></FONT> </DIV>
<DIV> </DIV>
<DIV><FONT size=2>while(1){<BR> <BR> /* Receive control
and data packets */<BR> timeout.tv_sec =
0;<BR> timeout.tv_usec = 5;<BR> rtp_recv(session,
&timeout, rtp_ts);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* State maintenance
*/<BR> rtp_update(session);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> <A
href="file://sleep">file://sleep</A>(1);<BR> xmemchk();<BR> }<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static int recieverCallback(void *data)<BR>{<BR> struct
timeval timeout;<BR> int retcode;<BR> <BR>#ifdef
WIN32<BR> WSADATA WSAdata;<BR> if (WSAStartup(WS_VERSION_TWO,
&WSAdata) != 0 && WSAStartup(WS_VERSION_ONE, &WSAdata) != 0)
{<BR> printf("Windows Socket initialization
failed.\n");<BR> return 1;<BR> }<BR> debug_msg("WSAStartup
OK: %sz\nStatus:%s\n", WSAdata.szDescription,
WSAdata.szSystemStatus);<BR>#endif<BR> <BR>// memcpy(address,&data[sizeof(uint16_t)],sizeof(uint16_t));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR>printf("Started thread %s: My thread id is %u\n",(char
*)data, SDL_ThreadID());<BR> session = rtp_init((char *)data, /*
Host/Group IP address */ <BR> 8000, /*
receive port */<BR> 8000, /* transmit
port */<BR> 16, /* time-to-live
*/<BR> 64000, /* B/W estimate
*/<BR> rtp_event_handler, /* RTP event
callback */<BR> NULL); /* App. specific
data */</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (session) {<BR> const char
*username = "Malcovich Malcovitch";<BR> const
char *telephone = "1-800-RTP-DEMO";<BR> const
char *toolname = "RTPdemo";</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> uint32_t my_ssrc =
rtp_my_ssrc(session);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Set local participant info
*/<BR> rtp_set_sdes(session, my_ssrc,
RTCP_SDES_NAME,<BR> username,
strlen(username));<BR> rtp_set_sdes(session, my_ssrc,
RTCP_SDES_PHONE,<BR> telephone,
strlen(telephone));<BR> rtp_set_sdes(session, my_ssrc,
RTCP_SDES_TOOL,<BR> toolname,
strlen(toolname));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Filter out local packets if requested
*/<BR> rtp_set_option(session, RTP_OPT_FILTER_MY_PACKETS,
0);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Run main loop
*/<BR> recieve_packet(session, 0);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Say bye-bye
*/<BR> rtp_send_bye(session);<BR> rtp_done(session);<BR> }
else {<BR> printf("Could not initialize session for %s port
%d\n",<BR> (char
*)data,<BR>
8000);<BR> return -1;<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR>#ifdef
WIN32<BR> Sleep(2000);<BR> WSACleanup();<BR>#endif</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> return(0);<BR>}<BR>/**/<BR>static void
prepareBuffer()<BR>{<BR>uint32_t index=0;<BR>PCM_DATA_T *
temp=&header;<BR>uint16_t Buffer[2][1152];<BR> mp3data_struct
mp3data;<BR> int counter=0;<BR> #define MP3SIZE
1024*2<BR> uint8_t mp3buf[MP3SIZE];<BR> uint32_t
ret=0;<BR> mp3data.samplerate=22050;<BR>
mp3data.stereo=1;<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>do{ <BR> counter++;<BR> printf("the current
value2 is %d
\n",SDL_SemValue(sem));<BR> fflush(stdout);<BR> SDL_SemWait(sem);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT
size=2> SDL_mutexP(mutex);<BR> if(header.next
!=NULL)<BR> temp=header.next ;//move next</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>
memcpy(mp3buf,temp->data,temp->data_len);<BR>
SDL_mutexV(mutex);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>if(temp->data_len >0)<BR> ret =
lame_decode1_headers(mp3buf, temp->data_len , Buffer[0], Buffer[1],
&mp3data);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> header.next =temp->next
;<BR> if(temp->data!=NULL) <BR> { printf("free
temp->data now");<BR> free(temp->data);<BR>
}<BR> if(temp!=NULL) <BR> {<BR> printf("free temp
now");<BR> free(temp);<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> <BR>
memcpy(&pcmBuffer[index],Buffer[0] ,ret);<BR> index+=ret
;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR> }while(index+500<MAXPCM);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><A
href="file://}">file://}</A>while(counter<40);<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static void audioCallback(void *unused, Uint8 *stream, int
len)<BR>{<BR> <BR>#ifdef OLD</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> Uint8 *waveptr;<BR> int
waveleft;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Set up the pointers */<BR> waveptr = sound +
soundpos;<BR> waveleft = soundlen - soundpos;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Go!
*/<BR> SDL_mutexP(mutex);<BR> <BR> while ( waveleft <= len )
{<BR> SDL_MixAudio(stream, waveptr, waveleft,
SDL_MIX_MAXVOLUME);<BR> stream += waveleft;<BR> len -=
waveleft;<BR> waveptr = sound;<BR> waveleft =
soundlen;<BR> soundpos = 0;<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR> SDL_MixAudio(stream, waveptr, len,
SDL_MIX_MAXVOLUME);<BR> SDL_mutexV(mutex);<BR> soundpos +=
len;<BR>#else<BR> if(soundlen<=0)
<BR> return;<BR>
len=(len>soundlen?soundlen:len);<BR> printf("the callback return
len=%d\n",len);<BR> SDL_MixAudio(stream,sound,len,SDL_MIX_MAXVOLUME);<BR> sound+=len;<BR> soundlen-=len;<BR>#endif</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>}<BR>/*the callback function of thread player*/</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>static int playerCallback(void *data)<BR>{<BR> int
lameret=0;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> SDL_AudioSpec *desired, *obtained;<BR> /*
Allocate a desired SDL_AudioSpec */<BR>desired=(SDL_AudioSpec
*)malloc(sizeof(SDL_AudioSpec));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* Allocate space for the obtained SDL_AudioSpec
*/<BR>obtained=(SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* 22050Hz - FM Radio quality
*/<BR>desired->freq=22050;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* 16-bit signed audio
*/<BR>desired->format=AUDIO_S16LSB;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* Mono */<BR>desired->channels=1;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* Large audio buffer reduces risk of dropouts but increases
response time */<BR>desired->samples=8192;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/* Our callback function
*/<BR>desired->callback=audioCallback;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>desired->userdata=NULL;<BR> if (
SDL_OpenAudio(desired,obtained) < 0 ) {<BR> fprintf(stderr,
"Couldn't open audio: %s\n",
SDL_GetError());<BR> <BR> exit(2);<BR> }<BR> free(desired);<BR>printf("I
have walk into player thread and going to
prepareBuffer\n");<BR> /*prepare data mainly get rid of the queue and
add it to a big buffer*/<BR>
SDL_Delay(4000);<BR> printf("delay ok! going to prepare
buffer");</FONT></DIV>
<DIV> </DIV>
<DIV><FONT
size=2> <BR> lameret=lame_decode_init();<BR>printf("lame decode
init ret %d\n",lameret);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> while(1)<BR> {<BR>
prepareBuffer();<BR> sound=pcmBuffer;<BR> soundpos=0;<BR> soundlen=MAXPCM-500;<BR> SDL_PauseAudio(0);<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Let the audio run */<BR>// printf("Using audio
driver: %s\n", SDL_AudioDriverName(name, 32));<BR> while (1
)<BR> SDL_Delay(1000);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> /* Clean up on signal
*/<BR> SDL_CloseAudio();<BR>}</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2>/*
-------------------------------------------------------------------------
*/<BR>/* Main loop: parses command line and initializes RTP session */<BR>int
main(int argc,char* argv[])<BR>{</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> int32_t ac, filter_me = 0, send_enable =
0;<BR> char *address = NULL;<BR> uint16_t port
= 0;<BR> SDL_Thread * reciever;<BR> SDL_Thread * player;<BR>
int init_sem=0;<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> ac = 1;<BR> while (argv[ac][0] == '-')
{<BR> switch(tolower(argv[ac][1])) {<BR> case
'f':<BR> filter_me =
1;<BR> break;<BR> case
'l':<BR> send_enable =
0;<BR> break;<BR> }<BR> ac++;<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if (argc - ac != 2)
{<BR> usage();<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> address = argv[ac];<BR> port =
atoi(argv[ac + 1]);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2></FONT> </DIV>
<DIV> </DIV>
<DIV><FONT size=2> if ( SDL_Init(0) < 0 )
<BR> { fprintf(stderr, "Couldn't initialize SDL:
%s\n",SDL_GetError());<BR>
exit(1); <BR>
}<BR> <BR> atexit(SDL_Quit);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> sem =
SDL_CreateSemaphore(init_sem);</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> if ( (mutex=SDL_CreateMutex()) == NULL )
<BR> { fprintf(stderr, "Couldn't create mutex: %s\n",
SDL_GetError());<BR>
exit(1);<BR> }</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2><BR> <BR>reciever =
SDL_CreateThread(recieverCallback,address);<BR>player=
SDL_CreateThread(playerCallback,"player");<BR>SDL_WaitThread(reciever,
NULL);<BR>SDL_WaitThread(player, NULL);<BR> </FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2> return 0;<BR>}<BR></FONT></DIV>
<DIV><FONT size=2> </FONT> </DIV></BODY></HTML>