示例#1
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;     /* Holds the stream properties */
    size_t resume_offset;
    int res;                    /* Return values from asf_read_packet() and decode_packet() */
    uint8_t* audiobuf;          /* Pointer to the payload of one wma pro packet */
    int audiobufsize;           /* Payload size */
    int packetlength = 0;       /* Logical packet size (minus the header size) */          
    int outlen = 0;             /* Number of bytes written to the output buffer */
    int pktcnt = 0;             /* Count of the packets played */

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
    

next_track:
    retval = CODEC_OK;

    /* Wait for the metadata to be read */
    if (codec_wait_taginfo() != 0)
        goto done;

    /* Remember the resume position */
    resume_offset = ci->id3->offset;
restart_track:
    retval = CODEC_OK;

    if (codec_init()) {
        LOGF("(WMA Voice) Error: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));
    memset(&avctx, 0, sizeof(AVCodecContext));
    memset(&avpkt, 0, sizeof(AVPacket));
    
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_INTERLEAVED);
    codec_set_replaygain(ci->id3);
    
    /* Initialise the AVCodecContext */
    init_codec_ctx(&avctx, &wfx);

    if (wmavoice_decode_init(&avctx) < 0) {
        LOGF("(WMA Voice) Error: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Now advance the file position to the first frame */
    ci->seek_buffer(ci->id3->first_frame_offset);
    
    elapsedtime = 0;
    resume_offset = 0;
    
    /* The main decoding loop */

    while (pktcnt < wfx.numpackets)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }
        
        /* Deal with any pending seek requests */
        if (ci->seek_time){

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1){
                ci->seek_complete();
                goto next_track;
            }

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }
        
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            LOGF("(WMA Voice) read_packet error %d\n",res);
            goto done;
        } else {
            avpkt.data = audiobuf;
            avpkt.size = audiobufsize;
            pktcnt++;
            
            while(avpkt.size > 0)
            {
                /* wmavoice_decode_packet checks for the output buffer size to 
                   avoid overflows */
                outlen = BUFSIZE*sizeof(int32_t);

                res = wmavoice_decode_packet(&avctx, decoded, &outlen, &avpkt);
                if(res < 0) {
                    LOGF("(WMA Voice) Error: decode_packet returned %d", res);
                    if(res == ERROR_WMAPRO_IN_WMAVOICE){
                    /* Just skip this packet */
                        ci->advance_buffer(packetlength);
                        goto new_packet;    
                    }
                    else
                        goto done;
                }
                avpkt.data += res;
                avpkt.size -= res;
                if(outlen) {
                    ci->yield ();
                    outlen /= sizeof(int32_t);
                    ci->pcmbuf_insert(decoded, NULL, outlen);
                    elapsedtime += outlen*10/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                    ci->yield ();
                }
            }

        }

        /* Advance to the next logical packet */
        ci->advance_buffer(packetlength);
    }

done:
    if (ci->request_next_track())
        goto next_track;
    
    return retval;
}
示例#2
0
文件: wmapro.c 项目: ntj/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;     /* Holds the stream properties */
    size_t resume_offset;
    int res;                    /* Return values from asf_read_packet() and decode_packet() */
    uint8_t* audiobuf;          /* Pointer to the payload of one wma pro packet */
    int audiobufsize;           /* Payload size */
    int packetlength = 0;       /* Logical packet size (minus the header size) */
    int outlen = 0;             /* Number of bytes written to the output buffer */
    int pktcnt = 0;             /* Count of the packets played */
    uint8_t *data;              /* Pointer to decoder input buffer */
    int size;                   /* Size of the input frame to the decoder */

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH);


next_track:

    /* Wait for the metadata to be read */
    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    retval = CODEC_OK;

    /* Remember the resume position */
    resume_offset = ci->id3->offset;
restart_track:
    if (codec_init()) {
        LOGF("(WMA PRO) Error: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    if (decode_init(&wfx) < 0) {
        LOGF("(WMA PRO) Error: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Now advance the file position to the first frame */
    ci->seek_buffer(ci->id3->first_frame_offset);

    elapsedtime = 0;
    resume_offset = 0;

    /* The main decoding loop */

    while (pktcnt < wfx.numpackets)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }

        /* Deal with any pending seek requests */
        if (ci->seek_time) {

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1) {
                ci->seek_complete();
                goto next_track;
            }

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }

        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res);
            goto done;
        } else {
            data = audiobuf;
            size = audiobufsize;
            pktcnt++;

            /* We now loop on the packet, decoding and outputting the subframes
             * one-by-one. For more information about how wma pro structures its
             * audio frames, see libwmapro/wmaprodec.c */
            while(size > 0)
            {
                res = decode_packet(&wfx, dec, &outlen, data, size);
                if(res < 0) {
                    LOGF("(WMA PRO) Error: decode_packet returned %d", res);
                    goto done;
                }
                data += res;
                size -= res;
                if(outlen) {
                    ci->yield ();
                    outlen /= (wfx.channels);
                    ci->pcmbuf_insert(dec[0], dec[1], outlen );
                    elapsedtime += outlen*10/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                    ci->yield ();
                }
            }

        }

        /* Advance to the next logical packet */
        ci->advance_buffer(packetlength);
    }
    retval = CODEC_OK;

done:
    if (ci->request_next_track())
        goto next_track;

    return retval;
}
示例#3
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    uint32_t elapsedtime;
    asf_waveformatex_t wfx;
    size_t resume_offset;
    int i;
    int wmares;
    int res = 0;
    uint8_t* audiobuf;
    int audiobufsize;
    int packetlength = 0;
    int errcount = 0;
    intptr_t param;

    /* Proper reset of the decoder context. */
    memset(&wmadec, 0, sizeof(wmadec));

    /* Remember the resume position - when the codec is opened, the
       playback engine will reset it. */
    resume_offset = ci->id3->offset;

restart_track:
    if (codec_init()) {
        LOGF("WMA: Error initialising codec\n");
        return CODEC_ERROR;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    ci->seek_buffer(ci->id3->first_frame_offset);
    if (wma_decode_init(&wmadec,&wfx) < 0) {
        LOGF("WMA: Unsupported or corrupt file\n");
        return CODEC_ERROR;
    }

    if (resume_offset > ci->id3->first_frame_offset)
    {
        /* Get start of current packet */
        int packet_offset = (resume_offset - ci->id3->first_frame_offset)
            % wfx.packet_size;
        ci->seek_buffer(resume_offset - packet_offset);
        elapsedtime = asf_get_timestamp(&i);
    }
    else
    {
        /* Now advance the file position to the first frame */
        ci->seek_buffer(ci->id3->first_frame_offset);
        elapsedtime = 0;
    }

    ci->set_elapsed(elapsedtime);

    resume_offset = 0;
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    /* The main decoding loop */
    while (res >= 0)
    {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {

            if (param == 0) {
                ci->set_elapsed(0);
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(param, &wfx);
            if (elapsedtime < 1){
                ci->set_elapsed(0);
                ci->seek_complete();
                break;
            }
            /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/

            /*flush the wma decoder state*/
            wmadec.last_superframe_len = 0;
            wmadec.last_bitoffset = 0;

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }
        errcount = 0;
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            /* We'll try to recover from a parse error a certain number of
             * times. If we succeed, the error counter will be reset.
             */

            if (res == ASF_ERROR_EOF) {
                /* File ended - not an error */
                break;
            }

            errcount++;
            DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
            if (errcount > 5) {
                return CODEC_ERROR;
            } else {
                ci->advance_buffer(packetlength);
                goto new_packet;
            }
        } else if (res > 0) {
            wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);

            for (i=0; i < wmadec.nb_frames; i++)
            {
                wmares = wma_decode_superframe_frame(&wmadec,
                                                     audiobuf, audiobufsize);

                ci->yield ();

                if (wmares < 0) {
                    /* Do the above, but for errors in decode. */
                    errcount++;
                    DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
                    if (errcount > 5) {
                        return CODEC_ERROR;
                    } else {
                        ci->advance_buffer(packetlength);
                        goto new_packet;
                    }
                } else if (wmares > 0) {
                    ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
                    elapsedtime += (wmares*10)/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                }
            }
        }

        ci->advance_buffer(packetlength);
    }

    /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/
    return CODEC_OK;
}
示例#4
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;
    size_t resume_offset;
    int i;
    int wmares, res;
    uint8_t* audiobuf;
    int audiobufsize;
    int packetlength = 0;
    int errcount = 0;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 29);

next_track:

    /* Wait for the metadata to be read */
    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    retval = CODEC_OK;

    /* Remember the resume position - when the codec is opened, the
       playback engine will reset it. */
    resume_offset = ci->id3->offset;
restart_track:
    if (codec_init()) {
        LOGF("WMA: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    if (wma_decode_init(&wmadec,&wfx) < 0) {
        LOGF("WMA: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    if (resume_offset > ci->id3->first_frame_offset)
    {
        /* Get start of current packet */
        int packet_offset = (resume_offset - ci->id3->first_frame_offset)
            % wfx.packet_size;
        ci->seek_buffer(resume_offset - packet_offset);
        elapsedtime = asf_get_timestamp(&i);
        ci->set_elapsed(elapsedtime);
    }
    else
    {
        /* Now advance the file position to the first frame */
        ci->seek_buffer(ci->id3->first_frame_offset);
        elapsedtime = 0;
    }

    resume_offset = 0;
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    /* The main decoding loop */

    res = 1;
    while (res >= 0)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }

        /* Deal with any pending seek requests */
        if (ci->seek_time){

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1){
                ci->seek_complete();
                goto next_track;
            }
            /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/
            ci->set_elapsed(elapsedtime);

            /*flush the wma decoder state*/
            wmadec.last_superframe_len = 0;
            wmadec.last_bitoffset = 0;
            ci->seek_complete();
        }
        errcount = 0;
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            /* We'll try to recover from a parse error a certain number of
             * times. If we succeed, the error counter will be reset.
             */

            errcount++;
            DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
            if (errcount > 5) {
                goto done;
            } else {
                ci->advance_buffer(packetlength);
                goto new_packet;
            }
        } else if (res > 0) {
            wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);

            for (i=0; i < wmadec.nb_frames; i++)
            {
                wmares = wma_decode_superframe_frame(&wmadec,
                                                     audiobuf, audiobufsize);

                ci->yield ();

                if (wmares < 0) {
                    /* Do the above, but for errors in decode. */
                    errcount++;
                    DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
                    if (errcount > 5) {
                        goto done;
                    } else {
                        ci->advance_buffer(packetlength);
                        goto new_packet;
                    }
                } else if (wmares > 0) {
                    ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
                    elapsedtime += (wmares*10)/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                }
                ci->yield();
            }
        }

        ci->advance_buffer(packetlength);
    }
    retval = CODEC_OK;

done:
    /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/

    if (ci->request_next_track())
        goto next_track;
exit:
    return retval;
}