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 + -
显示快捷键?