Index: wma.c =================================================================== --- wma.c (revision 14224) +++ wma.c (working copy) @@ -21,6 +21,8 @@ #include "libwma/asf.h" #include "libwma/wmadec.h" +int packet_count=0; + CODEC_HEADER /* The output buffer containing the decoded samples (channels 0 and 1) @@ -152,7 +154,7 @@ datap += 4; duration = get_short_le(datap); datap += 2; - + DEBUGF("packet #%d reports length of %d ms (%d samples) at %d bytes\n", ++packet_count, duration, duration*wfx->rate/1000, ci->curpos-bytesread); /* this is really idiotic, packet length can (and often will) be * undefined and we just have to use the header packet size as the size * value */ @@ -249,7 +251,6 @@ /* TODO: Is the content of this important for us? */ datap += replicated_length; bytesread += replicated_length; - multiple = packet_flags & 0x01; if (multiple) { @@ -300,6 +301,197 @@ return 0; } +static int skip_packet(asf_waveformatex_t* wfx){ + + uint8_t tmp8, packet_flags, packet_property; + int stream_id; + int ec_length, opaque_data, ec_length_type; + int datalen; + uint8_t data[18]; + uint8_t* datap; + uint32_t length; + uint32_t padding_length; + uint32_t send_time; + uint16_t duration; + uint16_t payload_count; + uint32_t bytesread = 0; + packet_count++; + if (ci->read_filebuf(&tmp8, 1) == 0) { + DEBUGF("ASF ERROR (EOF?)\n"); + return ASF_ERROR_EOF; + } + bytesread++; + + //DEBUGF("tmp8=0x%02x\n",tmp8); + /* TODO: We need a better way to detect endofstream */ + if (tmp8 != 0x82) { + DEBUGF("Detected end of stream\n"); + + return -1; } + + + if (tmp8 & 0x80) { + ec_length = tmp8 & 0x0f; + opaque_data = (tmp8 >> 4) & 0x01; + ec_length_type = (tmp8 >> 5) & 0x03; + + if (ec_length_type != 0x00 || opaque_data != 0 || ec_length != 0x02) { + DEBUGF("incorrect error correction flags\n"); + return ASF_ERROR_INVALID_VALUE; + } + + /* Skip ec_data */ + ci->advance_buffer(ec_length); + bytesread += ec_length; + } else { + ec_length = 0; + } + + if (ci->read_filebuf(&packet_flags, 1) == 0) { DEBUGF("Detected end of stream 2\n"); return ASF_ERROR_EOF; } + if (ci->read_filebuf(&packet_property, 1) == 0) {DEBUGF("Detected end of stream3\n"); return ASF_ERROR_EOF; } + bytesread += 2; + + datalen = GETLEN2b((packet_flags >> 1) & 0x03) + + GETLEN2b((packet_flags >> 3) & 0x03) + + GETLEN2b((packet_flags >> 5) & 0x03) + 6; + + if (ci->read_filebuf(data, datalen) == 0) { + DEBUGF("Detected end of stream4\n"); + return ASF_ERROR_EOF; + } + + bytesread += datalen; + + datap = data; + length = GETVALUE2b((packet_flags >> 5) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 5) & 0x03); + /* sequence value is not used */ + GETVALUE2b((packet_flags >> 1) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 1) & 0x03); + padding_length = GETVALUE2b((packet_flags >> 3) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 3) & 0x03); + send_time = get_long_le(datap); + datap += 4; + duration = get_short_le(datap); + // datap += 2; + + /*now jump to the end of the packet*/ + ci->advance_buffer(wfx->packet_size - (bytesread)); + DEBUGF("skipped ahead %d milliseconds (packet #%d was %d bytes)\n", duration, packet_count, wfx->packet_size); + return duration; +} + + +static int prev_packet(asf_waveformatex_t* wfx){ + + uint8_t tmp8, packet_flags, packet_property; + int stream_id; + int ec_length, opaque_data, ec_length_type; + int datalen; + uint8_t data[18]; + uint8_t* datap; + uint32_t length; + uint32_t padding_length; + uint32_t send_time; + uint16_t duration; + uint16_t payload_count; + uint32_t bytesread = 0; + packet_count--; + + /*now jump to the start of the previous packet of the packet*/ + ci->advance_buffer(wfx->packet_size - (bytesread)); + + if (ci->read_filebuf(&tmp8, 1) == 0) { + DEBUGF("ASF ERROR (EOF?)\n"); + return ASF_ERROR_EOF; + } + bytesread++; + + //DEBUGF("tmp8=0x%02x\n",tmp8); + /* TODO: We need a better way to detect endofstream */ + if (tmp8 != 0x82) { + DEBUGF("Detected end of stream\n"); + + return -1; } + + + if (tmp8 & 0x80) { + ec_length = tmp8 & 0x0f; + opaque_data = (tmp8 >> 4) & 0x01; + ec_length_type = (tmp8 >> 5) & 0x03; + + if (ec_length_type != 0x00 || opaque_data != 0 || ec_length != 0x02) { + DEBUGF("incorrect error correction flags\n"); + return ASF_ERROR_INVALID_VALUE; + } + + /* Skip ec_data */ + ci->advance_buffer(ec_length); + bytesread += ec_length; + } else { + ec_length = 0; + } + + if (ci->read_filebuf(&packet_flags, 1) == 0) { DEBUGF("Detected end of stream 2\n"); return ASF_ERROR_EOF; } + if (ci->read_filebuf(&packet_property, 1) == 0) {DEBUGF("Detected end of stream3\n"); return ASF_ERROR_EOF; } + bytesread += 2; + + datalen = GETLEN2b((packet_flags >> 1) & 0x03) + + GETLEN2b((packet_flags >> 3) & 0x03) + + GETLEN2b((packet_flags >> 5) & 0x03) + 6; + + if (ci->read_filebuf(data, datalen) == 0) { + DEBUGF("Detected end of stream4\n"); + return ASF_ERROR_EOF; + } + + bytesread += datalen; + + datap = data; + length = GETVALUE2b((packet_flags >> 5) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 5) & 0x03); + /* sequence value is not used */ + GETVALUE2b((packet_flags >> 1) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 1) & 0x03); + padding_length = GETVALUE2b((packet_flags >> 3) & 0x03, datap); + datap += GETLEN2b((packet_flags >> 3) & 0x03); + send_time = get_long_le(datap); + datap += 4; + duration = get_short_le(datap); + // datap += 2; + + + DEBUGF("skipped back %d milliseconds (packet #%d was %d bytes)\n", duration, packet_count, wfx->packet_size); + return duration; +} + +static int seek(int ms, asf_waveformatex_t* wfx){ + int current_pos=0; + int ret; + /*TODO: Search backwards if the seek is negative*/ + + + /*step through the file one packet at a time reading the time stamps*/ + DEBUGF("beginning seek at %d bytes)\n", ci->curpos); + if(ms > 0){ /*fast forward*/ + + while (current_pos< ms){ + ret = skip_packet(wfx); + if(ret< 0) + return (current_pos); + else + current_pos += ret; + DEBUGF("at %d milliseconds (%d bytes), ret= %d\n", current_pos, ci->curpos, ret); + } + + }else{ + /*rewind*/ + + } + return (current_pos); + +} + /* this is the codec entry point */ enum codec_status codec_main(void) { @@ -374,9 +566,16 @@ } /* Deal with any pending seek requests - ignore them */ - if (ci->seek_time) + if (ci->seek_time) //time in ms { + DEBUGF("seeking\n"); + int seek_t = seek(ci->seek_time-samplesdone/wfx.rate*1000, &wfx); + /*convert seek_time (in ms) to samples*/ + samplesdone = ci->seek_time*wfx.rate/1000; ci->seek_complete(); + + /*TODO: Figure out what state is actually fixed by reiniting after seek*/ + wma_decode_init(&wmadec,&wfx); } res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);