Ticket #7285: media_mixer.diff

File media_mixer.diff, 7.3 KB (added by Pete, 12 years ago)

Media and Mixer patch to fix behaviour with short buffers

  • src/kits/media/MediaEventLooper.cpp

     
    222222            // only the scheduling latency).
    223223
    224224            latency = fEventLatency + fSchedulingLatency;
    225             if (fEventQueue.HasEvents() && (TimeSource()->Now() - latency) >= fEventQueue.FirstEventTime()) {
    226 //              printf("node %02d waiting for %12Ld that has already happened, now %12Ld\n", ID(), fEventQueue.FirstEventTime(), system_time());
     225            if (fEventQueue.HasEvents()
     226                && (TimeSource()->Now() + latency) >= fEventQueue.FirstEventTime()) {
     227//              printf("node %02ld waiting for %12Ld that already happened, now %12Ld(%Ld)\n",
     228//              ID(), fEventQueue.FirstEventTime(), TimeSource()->Now(), system_time());
    227229                is_realtime = false;
    228230                break;
    229231            }
    230             if (fRealTimeQueue.HasEvents() && (TimeSource()->RealTime() - fSchedulingLatency) >= fRealTimeQueue.FirstEventTime()) {
     232            if (fRealTimeQueue.HasEvents()
     233                && (TimeSource()->RealTime() + fSchedulingLatency) >= fRealTimeQueue.FirstEventTime()) {
    231234                latency = fSchedulingLatency;
    232235                is_realtime = true;
    233236                break;
     
    235238            waituntil = B_INFINITE_TIMEOUT;
    236239            if (fEventQueue.HasEvents()) {
    237240                waituntil = TimeSource()->RealTimeFor(fEventQueue.FirstEventTime(), latency);
    238 //              printf("node %02d waiting for %12Ld that will happen at %12Ld\n", ID(), fEventQueue.FirstEventTime(), waituntil);
     241//              printf("node %02ld waiting for %12Ld that will happen at %12Ld\n",
     242//                  ID(), fEventQueue.FirstEventTime(), waituntil);
    239243                is_realtime = false;
    240244            }
    241245            if (fRealTimeQueue.HasEvents()) {
     
    265269            if (is_realtime)
    266270                lateness = TimeSource()->RealTime() - event.event_time;
    267271            else
    268                 lateness = TimeSource()->RealTime() - TimeSource()->RealTimeFor(event.event_time, 0) + fEventLatency;
     272                lateness =
     273                    TimeSource()->RealTime() - TimeSource()->RealTimeFor(event.event_time, 0) + fEventLatency;
    269274            DispatchEvent(&event, lateness, is_realtime);
    270275        }
    271276    }
  • src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp

     
    8686#define FORMAT_USER_DATA_MAGIC_1    0xc84173bd
    8787#define FORMAT_USER_DATA_MAGIC_2    0x4af62b7d
    8888
    89 
    9089const static bigtime_t kMaxLatency = 150000;
    9190    // 150 ms is the maximum latency we publish
    9291
     
    109108    fInternalLatency(1),
    110109    fDisableStop(false),
    111110    fLastLateNotification(0)
     111//  fBlockRepeatNotify(0)
    112112{
    113113    BMediaNode::AddNodeKind(B_SYSTEM_MIXER);
    114114
     
    302302
    303303    //PRINT(4, "buffer received at %12Ld, should arrive at %12Ld, delta %12Ld\n", TimeSource()->Now(), buffer->Header()->start_time, TimeSource()->Now() - buffer->Header()->start_time);
    304304
     305    bigtime_t lateness =
     306        TimeSource()->RealTime() + EventLatency()
     307        - TimeSource()->RealTimeFor(buffer->Header()->start_time, 0);
     308    if (lateness > kMaxJitter) {
     309        printf("Buffer start=%Ld: received %Ld usec late at %Ld EventLatency=%Ld\n",
     310            buffer->Header()->start_time, lateness, TimeSource()->Now(),
     311            EventLatency());
     312// I believe this is pointless here, because the relevant run mode is the source, mot the mixer!
     313//      if (RunMode() == B_DROP_DATA || RunMode() == B_DECREASE_PRECISION
     314//          || RunMode() == B_INCREASE_LATENCY) {
     315        // Increase latency only if we didn't do it recently:
     316        if (TimeSource()->Now() >= fLastLateNotification) {
     317            debug_printf("mixer sending notify\n");
     318
     319            // Build a media_source out of the header data
     320            media_source source = media_source::null;
     321            source.port = buffer->Header()->source_port;
     322            source.id = buffer->Header()->source;
     323
     324            NotifyLateProducer(source, lateness, TimeSource()->Now());
     325            // Don't send another before this:
     326            fLastLateNotification = buffer->Header()->start_time;
     327        }
     328
     329        if (RunMode() == B_DROP_DATA || lateness > EventLatency()) { // Experimental limit
     330            debug_printf("Mixer dropping buffer\n");
     331            return;
     332        }
     333    }
    305334    // to receive the buffer at the right time,
    306335    // push it through the event looper
    307336    media_timed_event event(buffer->Header()->start_time,
    308337        BTimedEventQueue::B_HANDLE_BUFFER, buffer,
    309338        BTimedEventQueue::B_RECYCLE_BUFFER);
    310339    EventQueue()->AddEvent(event);
     340
    311341}
    312342
    313343
    314344void
    315345AudioMixer::HandleInputBuffer(BBuffer* buffer, bigtime_t lateness)
    316346{
    317     if (lateness > kMaxJitter) {
    318         debug_printf("Received buffer %Ld usec late\n", lateness);
    319         if (RunMode() == B_DROP_DATA || RunMode() == B_DECREASE_PRECISION
    320             || RunMode() == B_INCREASE_LATENCY) {
    321             debug_printf("sending notify\n");
    322 
    323             // Build a media_source out of the header data
    324             media_source source = media_source::null;
    325             source.port = buffer->Header()->source_port;
    326             source.id = buffer->Header()->source;
    327 
    328             NotifyLateProducer(source, lateness, TimeSource()->Now());
    329 
    330             if (RunMode() == B_DROP_DATA) {
    331                 debug_printf("dropping buffer\n");
    332                 return;
    333             }
    334         }
     347    // Handle possible 'blackouts' in MediaEventLooper timing:
     348    bigtime_t real_lateness = TimeSource()->RealTime() + fDownstreamLatency
     349        - TimeSource()->RealTimeFor(buffer->Header()->start_time, 0);
     350    // Increase latency only if we didn't do it recently
     351    // -- because we don't want to respond to multiple reports from buffers in the queue
     352    if (real_lateness > kMaxJitter && TimeSource()->Now() >= fLastLateNotification) {
     353        fInternalLatency += real_lateness;
     354        SetEventLatency(fDownstreamLatency + fInternalLatency);
     355        printf("Mixer: perftime %Ld actual lateness = %Ld reset event latency=%Ld\n",
     356            buffer->Header()->start_time, real_lateness,  EventLatency());
     357        PublishEventLatencyChange();
     358        fLastLateNotification = buffer->Header()->start_time;
    335359    }
    336360
    337361    //  printf("Received buffer with lateness %Ld\n", lateness);
     
    9981022
    9991023    ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", howMuch,
    10001024        performanceTime);
     1025    printf("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", howMuch,
     1026        performanceTime);
    10011027
    10021028    if (what == fCore->Output()->MediaOutput().source
    10031029        && RunMode() == B_INCREASE_LATENCY) {
    1004         // We need to ignore subsequent notices whose performance time
    1005         // lies before the performance time of the last notification
     1030        // We need to ignore subsequent notices whose arrival time here
     1031        // lies within the latency, because queued-up buffers will all be 'late'
    10061032        if (performanceTime < fLastLateNotification)
    10071033            return;
    10081034
    10091035        fInternalLatency += howMuch;
    10101036
    10111037        // At some point a too large latency can get annoying
     1038        // (actually more than annoying, as there won't be enough buffers long before this!)
    10121039        if (fInternalLatency > kMaxLatency)
    10131040            fInternalLatency = kMaxLatency;
    10141041
    1015         fLastLateNotification = TimeSource()->Now();
     1042        fLastLateNotification = TimeSource()->Now() + EventLatency();
    10161043
    10171044        debug_printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
     1045        printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
    10181046        SetEventLatency(fDownstreamLatency + fInternalLatency);
    10191047
    10201048        PublishEventLatencyChange();
     
    10661094    switch (event->type) {
    10671095        case BTimedEventQueue::B_HANDLE_BUFFER:
    10681096        {
     1097//          printf("Mixer HandleInputBuffer at %Ld\n", system_time());
    10691098            HandleInputBuffer((BBuffer *)event->pointer, lateness);
    10701099            ((BBuffer *)event->pointer)->Recycle();
    10711100            break;