Ignore:
Timestamp:
Mar 5, 2006 1:37:19 PM (18 years ago)
Author:
bennylp
Message:

Allow file port to read the file in chunks instead of a whole

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/file_port.c

    r277 r288  
    2323#include <pj/file_access.h> 
    2424#include <pj/file_io.h> 
     25#include <pj/log.h> 
    2526#include <pj/pool.h> 
    2627#include <pj/string.h> 
     28 
     29 
     30#define THIS_FILE   "file_port.c" 
     31 
     32 
     33#ifndef PJMEDIA_FILE_PORT_BUFSIZE 
     34#   define PJMEDIA_FILE_PORT_BUFSIZE    4000 
     35#endif 
    2736 
    2837 
     
    3544    char            *buf; 
    3645    char            *readpos; 
     46 
     47    pj_off_t         fsize; 
     48    pj_off_t         fpos; 
     49    pj_oshandle_t    fd; 
     50 
    3751}; 
    3852 
     
    7791 
    7892/* 
     93 * Fill buffer. 
     94 */ 
     95static pj_status_t fill_buffer(struct file_port *fport) 
     96{ 
     97    pj_ssize_t size_left = fport->bufsize; 
     98    unsigned size_to_read; 
     99    pj_ssize_t size; 
     100    pj_status_t status; 
     101 
     102    while (size_left > 0) { 
     103 
     104        /* Calculate how many bytes to read in this run. */ 
     105        size = size_to_read = size_left; 
     106        status = pj_file_read(fport->fd,  
     107                              &fport->buf[fport->bufsize-size_left],  
     108                              &size); 
     109        if (status != PJ_SUCCESS) 
     110            return status; 
     111        if (size < 0) { 
     112            /* Should return more appropriate error code here.. */ 
     113            return PJ_ECANCELLED; 
     114        } 
     115 
     116        size_left -= size; 
     117        fport->fpos += size; 
     118 
     119        /* If size is less than size_to_read, it indicates that we've 
     120         * encountered EOF. Rewind the file. 
     121         */ 
     122        if (size < (pj_ssize_t)size_to_read) { 
     123            PJ_LOG(5,(THIS_FILE, "File port %.*s EOF, rewinding..", 
     124                      (int)fport->base.info.name.slen, 
     125                      fport->base.info.name.ptr)); 
     126            fport->fpos = sizeof(struct pjmedia_wave_hdr); 
     127            pj_file_setpos( fport->fd, fport->fpos, PJ_SEEK_SET); 
     128        } 
     129    } 
     130 
     131    return PJ_SUCCESS; 
     132} 
     133 
     134/* 
    79135 * Create WAVE player port. 
    80136 */ 
     
    86142                                                     pjmedia_port **p_port ) 
    87143{ 
    88     pj_off_t file_size; 
    89     pj_oshandle_t fd = NULL; 
    90144    pjmedia_wave_hdr wave_hdr; 
    91145    pj_ssize_t size_read; 
    92     struct file_port *file_port; 
     146    struct file_port *fport; 
    93147    pj_status_t status; 
    94148 
     
    105159    } 
    106160 
     161    /* Create fport instance. */ 
     162    fport = create_file_port(pool); 
     163    if (!fport) { 
     164        return PJ_ENOMEM; 
     165    } 
     166 
     167 
    107168    /* Get the file size. */ 
    108     file_size = pj_file_size(filename); 
     169    fport->fsize = pj_file_size(filename); 
    109170 
    110171    /* Size must be more than WAVE header size */ 
    111     if (file_size <= sizeof(pjmedia_wave_hdr)) { 
     172    if (fport->fsize <= sizeof(pjmedia_wave_hdr)) { 
    112173        return PJMEDIA_ENOTVALIDWAVE; 
    113174    } 
    114175 
    115176    /* Open file. */ 
    116     status = pj_file_open( pool, filename, PJ_O_RDONLY, &fd); 
     177    status = pj_file_open( pool, filename, PJ_O_RDONLY, &fport->fd); 
    117178    if (status != PJ_SUCCESS) 
    118179        return status; 
     
    120181    /* Read the WAVE header. */ 
    121182    size_read = sizeof(wave_hdr); 
    122     status = pj_file_read( fd, &wave_hdr, &size_read); 
     183    status = pj_file_read( fport->fd, &wave_hdr, &size_read); 
    123184    if (status != PJ_SUCCESS) { 
    124         pj_file_close(fd); 
     185        pj_file_close(fport->fd); 
    125186        return status; 
    126187    } 
    127188    if (size_read != sizeof(wave_hdr)) { 
    128         pj_file_close(fd); 
     189        pj_file_close(fport->fd); 
    129190        return PJMEDIA_ENOTVALIDWAVE; 
    130191    } 
     
    135196        wave_hdr.fmt_hdr.fmt != PJMEDIA_FMT_TAG) 
    136197    { 
    137         pj_file_close(fd); 
     198        pj_file_close(fport->fd); 
    138199        return PJMEDIA_ENOTVALIDWAVE; 
    139200    } 
     
    144205        wave_hdr.fmt_hdr.block_align != 2) 
    145206    { 
    146         pj_file_close(fd); 
     207        pj_file_close(fport->fd); 
    147208        return PJMEDIA_EWAVEUNSUPP; 
    148209    } 
    149210 
    150211    /* Validate length. */ 
    151     if (wave_hdr.data_hdr.len != file_size-sizeof(pjmedia_wave_hdr)) { 
    152         pj_file_close(fd); 
     212    if (wave_hdr.data_hdr.len != fport->fsize-sizeof(pjmedia_wave_hdr)) { 
     213        pj_file_close(fport->fd); 
    153214        return PJMEDIA_EWAVEUNSUPP; 
    154215    } 
    155216    if (wave_hdr.data_hdr.len < 400) { 
    156         pj_file_close(fd); 
     217        pj_file_close(fport->fd); 
    157218        return PJMEDIA_EWAVETOOSHORT; 
    158219    } 
     
    160221    /* It seems like we have a valid WAVE file. */ 
    161222 
    162     /* Create file_port instance. */ 
    163     file_port = create_file_port(pool); 
    164     if (!file_port) { 
    165         pj_file_close(fd); 
     223    /* Initialize */ 
     224    fport->base.user_data = user_data; 
     225 
     226    /* Update port info. */ 
     227    fport->base.info.sample_rate = wave_hdr.fmt_hdr.sample_rate; 
     228    fport->base.info.bits_per_sample = wave_hdr.fmt_hdr.bits_per_sample; 
     229    fport->base.info.samples_per_frame = fport->base.info.sample_rate * 
     230                                             20 / 1000; 
     231    fport->base.info.bytes_per_frame =  
     232        fport->base.info.samples_per_frame *  
     233        fport->base.info.bits_per_sample / 8; 
     234 
     235    pj_strdup2(pool, &fport->base.info.name, filename); 
     236 
     237    /* Create file buffer. 
     238     */ 
     239    fport->bufsize = PJMEDIA_FILE_PORT_BUFSIZE; 
     240 
     241 
     242    /* Create buffer. */ 
     243    fport->buf = pj_pool_alloc(pool, fport->bufsize); 
     244    if (!fport->buf) { 
     245        pj_file_close(fport->fd); 
    166246        return PJ_ENOMEM; 
    167247    } 
    168248 
    169     /* Initialize */ 
    170     file_port->base.user_data = user_data; 
    171  
    172     /* Update port info. */ 
    173     file_port->base.info.sample_rate = wave_hdr.fmt_hdr.sample_rate; 
    174     file_port->base.info.bits_per_sample = wave_hdr.fmt_hdr.bits_per_sample; 
    175     file_port->base.info.samples_per_frame = file_port->base.info.sample_rate * 
    176                                              20 / 1000; 
    177     file_port->base.info.bytes_per_frame =  
    178         file_port->base.info.samples_per_frame *  
    179         file_port->base.info.bits_per_sample / 8; 
    180  
    181  
    182     /* For this version, we only support reading the whole 
    183      * contents of the file. 
    184      */ 
    185     file_port->bufsize = wave_hdr.data_hdr.len - 8; 
    186  
    187     /* Create buffer. */ 
    188     file_port->buf = pj_pool_alloc(pool, file_port->bufsize); 
    189     if (!file_port->buf) { 
    190         pj_file_close(fd); 
    191         return PJ_ENOMEM; 
    192     } 
    193  
    194     file_port->readpos = file_port->buf; 
    195  
    196     /* Read the the file. */ 
    197     size_read = file_port->bufsize; 
    198     status = pj_file_read(fd, file_port->buf, &size_read); 
     249    fport->readpos = fport->buf; 
     250 
     251    /* Set initial position of the file. */ 
     252    fport->fpos = sizeof(struct pjmedia_wave_hdr); 
     253 
     254    /* Fill up the buffer. */ 
     255    status = fill_buffer(fport); 
    199256    if (status != PJ_SUCCESS) { 
    200         pj_file_close(fd); 
     257        pj_file_close(fport->fd); 
    201258        return status; 
    202259    } 
    203260 
    204     if (size_read != (pj_ssize_t)file_port->bufsize) { 
    205         pj_file_close(fd); 
    206         return PJMEDIA_ENOTVALIDWAVE; 
    207     } 
    208  
    209  
    210261    /* Done. */ 
    211     pj_file_close(fd); 
    212  
    213     *p_port = &file_port->base; 
     262 
     263    *p_port = &fport->base; 
     264 
     265 
     266    PJ_LOG(4,(THIS_FILE,  
     267              "File port '%.*s' created: clock=%dKHz, bufsize=%uKB, " 
     268              "filesize=%luKB", 
     269              (int)fport->base.info.name.slen, 
     270              fport->base.info.name.ptr, 
     271              fport->base.info.sample_rate/1000, 
     272              fport->bufsize / 1000, 
     273              (unsigned long)(fport->fsize / 1000))); 
    214274 
    215275    return PJ_SUCCESS; 
     
    234294                                  pjmedia_frame *frame) 
    235295{ 
    236     struct file_port *port = (struct file_port*)this_port; 
     296    struct file_port *fport = (struct file_port*)this_port; 
    237297    unsigned frame_size; 
    238     pj_assert(port->base.info.signature == SIGNATURE); 
    239  
    240     frame_size = port->base.info.bytes_per_frame; 
     298    pj_status_t status; 
     299 
     300    pj_assert(fport->base.info.signature == SIGNATURE); 
     301 
     302    frame_size = fport->base.info.bytes_per_frame; 
     303    pj_assert(frame->size == frame_size); 
    241304 
    242305    /* Copy frame from buffer. */ 
     
    245308    frame->timestamp.u64 = 0; 
    246309 
    247     if (port->readpos + frame_size <= port->buf + port->bufsize) { 
    248         pj_memcpy(frame->buf, port->readpos, frame_size); 
    249         port->readpos += frame_size; 
    250         if (port->readpos == port->buf + port->bufsize) 
    251             port->readpos = port->buf; 
     310    if (fport->readpos + frame_size <= fport->buf + fport->bufsize) { 
     311 
     312        /* Read contiguous buffer. */ 
     313        pj_memcpy(frame->buf, fport->readpos, frame_size); 
     314 
     315        /* Fill up the buffer if all has been read. */ 
     316        fport->readpos += frame_size; 
     317        if (fport->readpos == fport->buf + fport->bufsize) { 
     318            fport->readpos = fport->buf; 
     319 
     320            status = fill_buffer(fport); 
     321            if (status != PJ_SUCCESS) 
     322                return status; 
     323        } 
    252324    } else { 
    253325        unsigned endread; 
    254326 
    255         endread = (port->buf+port->bufsize) - port->readpos; 
    256         pj_memcpy(frame->buf, port->readpos, endread); 
    257         pj_memcpy(((char*)frame->buf)+endread, port->buf, frame_size-endread); 
    258         port->readpos = port->buf + (frame_size - endread); 
     327        /* Split read. 
     328         * First stage: read until end of buffer.  
     329         */ 
     330        endread = (fport->buf+fport->bufsize) - fport->readpos; 
     331        pj_memcpy(frame->buf, fport->readpos, endread); 
     332 
     333        /* Second stage: fill up buffer, and read from the start of buffer. */ 
     334        status = fill_buffer(fport); 
     335        if (status != PJ_SUCCESS) { 
     336            pj_memset(((char*)frame->buf)+endread, 0, frame_size-endread); 
     337            return status; 
     338        } 
     339 
     340        pj_memcpy(((char*)frame->buf)+endread, fport->buf, frame_size-endread); 
     341        fport->readpos = fport->buf + (frame_size - endread); 
    259342    } 
    260343 
     
    267350static pj_status_t file_on_destroy(pjmedia_port *this_port) 
    268351{ 
    269     PJ_UNUSED_ARG(this_port); 
     352    struct file_port *fport = (struct file_port*) this_port; 
    270353 
    271354    pj_assert(this_port->info.signature == SIGNATURE); 
    272355 
     356    pj_file_close(fport->fd); 
    273357    return PJ_SUCCESS; 
    274358} 
Note: See TracChangeset for help on using the changeset viewer.