wav_playlist.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 629 行 · 第 1/2 页

C
629
字号
    /* ok run this for all files to be sure all are good for playback. */    for (index=file_count-1; index>=0; index--) {	pjmedia_wave_hdr wavehdr;	pj_ssize_t size_to_read, size_read;	/* we end with the last one so we are good to go if still in function*/	pj_memcpy(filename, file_list[index].ptr, file_list[index].slen);	filename[file_list[index].slen] = '\0';	/* Get the file size. */	fport->current_file = index;	fport->fsize_list[index] = pj_file_size(filename);		/* Size must be more than WAVE header size */	if (fport->fsize_list[index] <= sizeof(pjmedia_wave_hdr)) {	    status = PJMEDIA_ENOTVALIDWAVE;	    goto on_error;	}		/* Open file. */	status = pj_file_open( pool, filename, PJ_O_RDONLY, 			       &fport->fd_list[index]);	if (status != PJ_SUCCESS)	    goto on_error;		/* Read the file header plus fmt header only. */	size_read = size_to_read = sizeof(wavehdr) - 8;	status = pj_file_read( fport->fd_list[index], &wavehdr, &size_read);	if (status != PJ_SUCCESS) {	    goto on_error;	}	if (size_read != size_to_read) {	    status = PJMEDIA_ENOTVALIDWAVE;	    goto on_error;	}		/* Normalize WAVE header fields values from little-endian to host	 * byte order.	 */	pjmedia_wave_hdr_file_to_host(&wavehdr);		/* Validate WAVE file. */	if (wavehdr.riff_hdr.riff != PJMEDIA_RIFF_TAG ||	    wavehdr.riff_hdr.wave != PJMEDIA_WAVE_TAG ||	    wavehdr.fmt_hdr.fmt != PJMEDIA_FMT_TAG)	{	    TRACE_((THIS_FILE,		"actual value|expected riff=%x|%x, wave=%x|%x fmt=%x|%x",		wavehdr.riff_hdr.riff, PJMEDIA_RIFF_TAG,		wavehdr.riff_hdr.wave, PJMEDIA_WAVE_TAG,		wavehdr.fmt_hdr.fmt, PJMEDIA_FMT_TAG));	    status = PJMEDIA_ENOTVALIDWAVE;	    goto on_error;	}		/* Must be PCM with 16bits per sample */	if (wavehdr.fmt_hdr.fmt_tag != 1 ||	    wavehdr.fmt_hdr.bits_per_sample != 16)	{	    status = PJMEDIA_EWAVEUNSUPP;	    goto on_error;	}		/* Block align must be 2*nchannels */	if (wavehdr.fmt_hdr.block_align != 		wavehdr.fmt_hdr.nchan * BYTES_PER_SAMPLE)	{	    status = PJMEDIA_EWAVEUNSUPP;	    goto on_error;	}		/* If length of fmt_header is greater than 16, skip the remaining	 * fmt header data.	 */	if (wavehdr.fmt_hdr.len > 16) {	    size_to_read = wavehdr.fmt_hdr.len - 16;	    status = pj_file_setpos(fport->fd_list[index], size_to_read, 				    PJ_SEEK_CUR);	    if (status != PJ_SUCCESS) {		goto on_error;	    }	}		/* Repeat reading the WAVE file until we have 'data' chunk */	for (;;) {	    pjmedia_wave_subchunk subchunk;	    size_read = 8;	    status = pj_file_read(fport->fd_list[index], &subchunk, 				  &size_read);	    if (status != PJ_SUCCESS || size_read != 8) {		status = PJMEDIA_EWAVETOOSHORT;		goto on_error;	    }	    	    /* Normalize endianness */	    PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&subchunk);	    	    /* Break if this is "data" chunk */	    if (subchunk.id == PJMEDIA_DATA_TAG) {		wavehdr.data_hdr.data = PJMEDIA_DATA_TAG;		wavehdr.data_hdr.len = subchunk.len;		break;	    }	    	    /* Otherwise skip the chunk contents */	    size_to_read = subchunk.len;	    status = pj_file_setpos(fport->fd_list[index], size_to_read, 				    PJ_SEEK_CUR);	    if (status != PJ_SUCCESS) {		goto on_error;	    }	}		/* Current file position now points to start of data */	status = pj_file_getpos(fport->fd_list[index], &pos);	fport->start_data_list[index] = (unsigned)pos;		/* Validate length. */	if (wavehdr.data_hdr.len != fport->fsize_list[index] - 				       fport->start_data_list[index]) 	{	    status = PJMEDIA_EWAVEUNSUPP;	    goto on_error;	}	if (wavehdr.data_hdr.len < 400) {	    status = PJMEDIA_EWAVETOOSHORT;	    goto on_error;	}		/* It seems like we have a valid WAVE file. */		/* Update port info if we don't have one, otherwise check	 * that the WAV file has the same attributes as previous files. 	 */	if (!has_wave_info) {	    fport->base.info.channel_count = wavehdr.fmt_hdr.nchan;	    fport->base.info.clock_rate = wavehdr.fmt_hdr.sample_rate;	    fport->base.info.bits_per_sample = wavehdr.fmt_hdr.bits_per_sample;	    fport->base.info.samples_per_frame = fport->base.info.clock_rate *						 wavehdr.fmt_hdr.nchan *						 ptime / 1000;	    fport->base.info.bytes_per_frame =		fport->base.info.samples_per_frame *		fport->base.info.bits_per_sample / 8;	    has_wave_info = PJ_TRUE;	} else {	    /* Check that this file has the same characteristics as the other	     * files.	     */	    if (wavehdr.fmt_hdr.nchan != fport->base.info.channel_count ||		wavehdr.fmt_hdr.sample_rate != fport->base.info.clock_rate ||		wavehdr.fmt_hdr.bits_per_sample != fport->base.info.bits_per_sample)	    {		/* This file has different characteristics than the other 		 * files. 		 */		PJ_LOG(4,(THIS_FILE,		          "WAV playlist error: file '%s' has differrent number"			  " of channels, sample rate, or bits per sample",	      		  filename));		status = PJMEDIA_EWAVEUNSUPP;		goto on_error;	    }	}			/* Set initial position of the file. */	fport->fpos_list[index] = fport->start_data_list[index];    }    /* Fill up the buffer. */    status = file_fill_buffer(fport);    if (status != PJ_SUCCESS) {	goto on_error;    }        /* Done. */        *p_port = &fport->base;        PJ_LOG(4,(THIS_FILE,	     "WAV playlist '%.*s' created: samp.rate=%d, ch=%d, bufsize=%uKB",	     (int)port_label->slen,	     port_label->ptr,	     fport->base.info.clock_rate,	     fport->base.info.channel_count,	     fport->bufsize / 1000));        return PJ_SUCCESS;on_error:    for (index=0; index<file_count; ++index) {	if (fport->fd_list[index] != 0)	    pj_file_close(fport->fd_list[index]);    }    return status;}/* * Register a callback to be called when the file reading has reached the * end of the last file. */PJ_DEF(pj_status_t)pjmedia_wav_playlist_set_eof_cb(pjmedia_port *port,			        void *user_data,			        pj_status_t (*cb)(pjmedia_port *port,						  void *usr_data)){    struct playlist_port *fport;    /* Sanity check */    PJ_ASSERT_RETURN(port, PJ_EINVAL);    /* Check that this is really a playlist port */    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP);    fport = (struct playlist_port*) port;    fport->base.port_data.pdata = user_data;    fport->cb = cb;    return PJ_SUCCESS;}/* * Get frame from file for file_list operation */static pj_status_t file_list_get_frame(pjmedia_port *this_port,				       pjmedia_frame *frame){    struct playlist_port *fport = (struct playlist_port*)this_port;    unsigned frame_size;    pj_status_t status;    pj_assert(fport->base.info.signature == SIGNATURE);    //frame_size = fport->base.info.bytes_per_frame;    //pj_assert(frame->size == frame_size);    frame_size = frame->size;    /* Copy frame from buffer. */    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;    frame->size = frame_size;    frame->timestamp.u64 = 0;    if (fport->readpos + frame_size <= fport->buf + fport->bufsize) {	/* Read contiguous buffer. */	pj_memcpy(frame->buf, fport->readpos, frame_size);	/* Fill up the buffer if all has been read. */	fport->readpos += frame_size;	if (fport->readpos == fport->buf + fport->bufsize) {	    fport->readpos = fport->buf;	    status = file_fill_buffer(fport);	    if (status != PJ_SUCCESS) {		frame->type = PJMEDIA_FRAME_TYPE_NONE;		frame->size = 0;		return status;	    }	}    } else {	unsigned endread;	/* Split read.	 * First stage: read until end of buffer.	 */	endread = (fport->buf+fport->bufsize) - fport->readpos;	pj_memcpy(frame->buf, fport->readpos, endread);	/* Second stage: fill up buffer, and read from the start of buffer. */	status = file_fill_buffer(fport);	if (status != PJ_SUCCESS) {	    pj_bzero(((char*)frame->buf)+endread, frame_size-endread);	    return status;	}	pj_memcpy(((char*)frame->buf)+endread, fport->buf, frame_size-endread);	fport->readpos = fport->buf + (frame_size - endread);    }    return PJ_SUCCESS;}/* * Destroy port. */static pj_status_t file_list_on_destroy(pjmedia_port *this_port){    struct playlist_port *fport = (struct playlist_port*) this_port;    int index;    pj_assert(this_port->info.signature == SIGNATURE);    for (index=0; index<fport->max_file; index++)	pj_file_close(fport->fd_list[index]);    return PJ_SUCCESS;}

⌨️ 快捷键说明

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