Ignore:
Timestamp:
12/14/07 00:22:01 (16 years ago)
Author:
radscorpion
Message:

MPC Demux works. Right now it can only be used with Dump filter, because
it accepts any mediatype.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • dsfilters/demux_mpc/src/mpc_file.cpp

    r367 r368  
    1919        duration_10mhz(0),
    2020        reader(NULL),
    21         packet(NULL),
    2221        seek_table(NULL),
    2322        seek_table_position(0)
    2423{
    25         key = 0;
    26         packet_max_size = 512 * 1024;                   // well. hard to say. but I think this should be enough
    27         packet_size = 0;
    28         packet = (uint8*)malloc(packet_max_size);
    29 
    30         ASSERT(packet);
     24        extradata_max_size = 16*1024;                   // way too much..
     25        extradata_size = 0;
     26        extradata = (uint8*)malloc(extradata_max_size);
    3127}
    3228
    3329CMPCFile::~CMPCFile()
    3430{
    35         if (seek_table) {
    36                 free(seek_table);
    37                 seek_table = NULL;
    38         }
    39         if (packet) {
    40                 free(packet);
    41                 packet = NULL;
    42         }
     31        if (seek_table) { free(seek_table); seek_table = NULL; }
     32        if (extradata) { free(extradata); extradata = NULL; }
    4333}
    4434
     
    5242        // keep a local copy of the reader
    5343        this->reader = reader;
    54 
    5544
    5645        // According to stream specification the first 4 bytes should be 'MPCK'
     
    7059
    7160        // now loop through a few packets
     61        CMPCPacket              packet;
    7262        do {
    73                 ret = ReadNextPacket();
     63                ret = packet.Load(reader);
    7464                if (ret < 0) return -1;                 // end of file reached before initialization is done ?
    7565
    76                 switch (key) {
    77                 case MPC_KEY('S','H'):  ret = ReadStreamHeader(); break;
    78                 case MPC_KEY('R','G'):  ret = ReadReplaygain(); break;
    79                 case MPC_KEY('S','O'):  ret = ReadSeekOffset(); break;
     66                switch (packet.key) {
     67                case MPC_KEY('S','H'): 
     68                        ret = ReadStreamHeader(&packet);
     69                        StoreExtraDataPacket(&packet);
     70                        break;
     71                case MPC_KEY('R','G'): 
     72                        ret = ReadReplaygain(&packet);
     73                        StoreExtraDataPacket(&packet);
     74                        break;
     75                case MPC_KEY('S','O'): 
     76                        ret = ReadSeekOffset(&packet);
     77                        break;
     78                case MPC_KEY('E','I'):
     79                        StoreExtraDataPacket(&packet);
     80                        break;
    8081
    8182                // audio packet - initialization is over
     
    8990        // if there was a seek table, load it
    9091        if (seek_table_position != 0) {
    91                 ret = ReadSeekTable();
     92                int64 first_ap_pos, avail;
     93                reader->GetPosition(&first_ap_pos, &avail);
     94
     95                reader->Seek(seek_table_position);
     96                ret = packet.Load(reader);
     97                ret = ReadSeekTable(&packet);
    9298                if (ret < 0) return ret;
    93         }
    94 
    95         return 0;
    96 }
    97 
    98 int CMPCFile::ReadNextPacket()
    99 {
    100         uint16  key_val;
    101         int64   size_val;
    102         int32   size_len;
    103         int             ret;
    104         int64   avail;
    105 
    106         reader->GetPosition(&packet_pos, &avail);
    107         ret = reader->GetKey(key_val);                                  if (ret < 0) return ret;
    108         ret = reader->GetSizeElm(size_val, size_len);   if (ret < 0) return ret;
    109 
    110         // if the key is not valid, quit
    111         if (!reader->KeyValid(key_val)) return -1;
    112         key = key_val;
    113 
    114         // size_val is the total size including key, variable size field and payload
    115         packet_size = size_val - 2 - size_len;
    116         ASSERT(packet_size <= packet_max_size);
    117 
    118         ret = reader->Read(packet, packet_size);                if (ret < 0) return ret;
    119         return 0;
     99
     100                // seek back to first AP
     101                reader->Seek(first_ap_pos);
     102        }
     103
     104        // we're at start
     105        current_sample = 0;
     106        return 0;
     107}
     108
     109void CMPCFile::StoreExtraDataPacket(CMPCPacket *packet)
     110{
     111        // we add current packet to extradata
     112        uint8   *out = extradata + extradata_size;
     113        memcpy(out, packet->packet, packet->packet_size);
     114        extradata_size += packet->packet_size;
    120115}
    121116
    122117// parsing packets
    123 
    124 int CMPCFile::ReadReplaygain()
    125 {
    126         Bitstream       b(packet);
     118int CMPCFile::ReadReplaygain(CMPCPacket *packet)
     119{
     120        Bitstream       b(packet->payload);
    127121        b.NeedBits();
    128122
     
    139133}
    140134
    141 int CMPCFile::ReadSeekOffset()
    142 {
    143         Bitstream       b(packet);
     135int CMPCFile::ReadSeekOffset(CMPCPacket *packet)
     136{
     137        Bitstream       b(packet->payload);
    144138
    145139        seek_table_position = b.GetMpcSize();
    146         seek_table_position += packet_pos;
     140        seek_table_position += packet->file_position;
    147141
    148142        // success
     
    150144}
    151145
    152 int CMPCFile::ReadSeekTable()
    153 {
    154         reader->Seek(seek_table_position);
    155         int ret;
    156 
    157         ret = ReadNextPacket();
    158         if (ret < 0) return ret;
    159 
    160         Bitstream       b(packet);
     146int CMPCFile::ReadSeekTable(CMPCPacket *packet)
     147{
     148        Bitstream       b(packet->payload);
    161149
    162150        // calculate size as seen in mpc_demux.c
    163151        int64 tmp = b.GetMpcSize();     b.NeedBits();
    164152        seek_table_size = tmp;
    165         int     seek_pwr = block_pwr + b.UGetBits(4);
     153        seek_pwr = block_pwr + b.UGetBits(4);
    166154        tmp = 2+total_samples / (1152 << seek_pwr);
    167155        if (tmp < seek_table_size) tmp = seek_table_size;
     
    188176}
    189177
    190 int CMPCFile::ReadStreamHeader()
    191 {
    192         Bitstream       b(packet);
     178int CMPCFile::ReadStreamHeader(CMPCPacket *packet)
     179{
     180        Bitstream       b(packet->payload);
    193181        b.NeedBits();
    194182
     
    249237
    250238                        // store absolute position of stream header
    251                         header_position = packet_pos;
     239                        header_position = packet->file_position -4;
    252240                }
    253241                break;
     
    261249}
    262250
    263 
     251// parsing out packets
     252int CMPCFile::ReadAudioPacket(CMPCPacket *packet, int64 *cur_sample)
     253{
     254        // we just load packets until we face the SE packet. Then we return -1
     255        int ret;
     256
     257        do {
     258                ret = packet->Load(reader);
     259                if (ret < 0) return ret;
     260
     261                switch (packet->key) {
     262                case MPC_KEY('A','P'): 
     263                        {
     264                                // keep track of samples...
     265                                if (cur_sample) *cur_sample = current_sample;
     266                                current_sample += (1152*audio_block_frames);
     267
     268                                return 0;                       // we got one
     269                        }
     270                case MPC_KEY('S','E'):  return -1;                      // end of stream
     271                }
     272
     273                // skip other packets
     274        } while (1);
     275
     276        // unexpected...
     277        return 0;
     278}
     279
     280int CMPCFile::Seek(int64 seek_sample)
     281{
     282        /*
     283                This will be a little tricky. I would like to support also
     284                less precise seeking with files that don't have seeking table.
     285                But if there is one, we would use that one.
     286
     287                Original implementation also deals with introductory silence.
     288                But since I don't know of any dshow filters capable of
     289                gapless playback we would ignore this. Of course it can
     290                be implemented later.
     291
     292                It is absolutely okay to do AP-level seeking. The caller
     293                knows the exact time it wants to seek to and we will provide
     294                the nearest AP. If the requested time is in the middle of AP,
     295                the (current_time - requested_time) expression would be negative
     296                and decoder will skip samples until positive time values are encountered.
     297                This way we can do sample-precise seeking.
     298        */
     299
     300        // cannot seek
     301        if (seek_table == NULL || seek_table_size == 0) return -1;
     302
     303        int packet_num = seek_sample / (1152*audio_block_frames);
     304        int i = (packet_num >> (seek_pwr - block_pwr));
     305        if (i >= seek_table_size) {
     306                i = seek_table_size-1;
     307        }
     308
     309        // seek to position
     310        uint32 pos = seek_table[i] >> 3;
     311        reader->Seek(pos);
     312
     313        // shift back
     314        i = i << (seek_pwr - block_pwr);
     315        current_sample = i*audio_block_frames;
     316
     317        return 0;
     318}
     319
     320
     321//-----------------------------------------------------------------------------
     322//
     323//      CMPCPacket
     324//
     325//-----------------------------------------------------------------------------
     326
     327CMPCPacket::CMPCPacket() :
     328        file_position(0),
     329        packet(NULL),
     330        payload(NULL),
     331        packet_size(0),
     332        payload_size(0),
     333        key(0)
     334{
     335}
     336
     337CMPCPacket::~CMPCPacket()
     338{
     339        // just let it go
     340        Release();
     341}
     342
     343void CMPCPacket::Release()
     344{
     345        if (packet) { free(packet); packet = NULL; }
     346        payload = NULL;
     347        packet_size = 0;
     348        payload_size = 0;
     349        key = 0;
     350        file_position = 0;
     351}
     352
     353int CMPCPacket::Load(CMPCReader *reader)
     354{
     355        uint16  key_val;
     356        int64   size_val, avail;
     357        int32   size_len;
     358        int             ret;
     359        Release();
     360        reader->GetPosition(&file_position, &avail);
     361
     362        // end of stream
     363        if (file_position >= avail) return -1;
     364
     365        ret = reader->GetKey(key_val);                                  if (ret < 0) return ret;
     366        ret = reader->GetSizeElm(size_val, size_len);   if (ret < 0) return ret;
     367        // if the key is not valid, quit
     368        if (!reader->KeyValid(key_val)) return -1;
     369        key = key_val;
     370
     371        // now load the packet
     372        packet_size  = size_val;
     373        payload_size = size_val - 2 - size_len;
     374        packet = (uint8*)malloc(packet_size);
     375        payload = packet + 2 + size_len;                                // pointer to packet payload
     376
     377        // roll back the bytes
     378        reader->Seek(file_position);
     379        ret = reader->Read(packet, packet_size);                if (ret < 0) return ret;
     380
     381        return 0;
     382}
     383
     384
Note: See TracChangeset for help on using the changeset viewer.