Ticket #7285: media_mixer.2.diff

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

2nd version of the patch to fix latency problem

  • headers/private/media/ServerInterface.h

     
    3737
    3838// Raw port based communication
    3939enum {
     40    GENERAL_PURPOSE_WAKEUP = 0, // when no action but wait termination needed
     41   
    4042    ADD_ON_SERVER_RESCAN_ADD_ON_FLAVORS = 0x50,
    4143    ADD_ON_SERVER_RESCAN_FINISHED_NOTIFY,
    4244    ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE,
  • headers/os/media/TimedEventQueue.h

     
    3838            int32               data;
    3939            int64               bigdata;
    4040            char                user_data[64];
     41            bigtime_t           queued_time;    // Real time when put in queue
    4142
    42             uint32              _reserved_media_timed_event_[8];
     43            uint32              _reserved_media_timed_event_[6];
    4344};
    4445
    4546
  • src/kits/media/TimedEventQueuePrivate.cpp

     
    2929
    3030/* Implements _event_queue_imp used by BTimedEventQueue, not thread save!
    3131 */
    32 #include <TimedEventQueue.h>
     32#include <string.h>
     33
    3334#include <Autolock.h>
    3435#include <Buffer.h>
    3536#include <InterfaceDefs.h> //defines B_DELETE
     37#include <TimedEventQueue.h>
     38#include <TimeSource.h>
     39
    3640#include "TimedEventQueuePrivate.h"
     41
    3742#include "Debug.h"
    3843#include "debug.h"
    3944
    40 #include <string.h>
    41 
    4245_event_queue_imp::_event_queue_imp() :
    4346    fLock(new BLocker("BTimedEventQueue locker")),
    4447    fEventCount(0),
     
    7477    if (event.type <= 0) {
    7578         return B_BAD_VALUE;
    7679    }
     80   
     81    *(bigtime_t *)&event.queued_time = BTimeSource::RealTime();
    7782
    7883    //create a new queue
    7984    if (fFirstEntry == NULL) {
  • src/kits/media/MediaEventLooper.cpp

     
    3131#include <TimeSource.h>
    3232#include <scheduler.h>
    3333#include <Buffer.h>
     34#include <ServerInterface.h>
    3435#include "debug.h"
    3536
    3637/*************************************************************
     
    210211    status_t err;
    211212    bigtime_t latency;
    212213    bigtime_t waituntil;
     214    bigtime_t lateness;
    213215    for (;;) {
    214216        // while there are no events or it is not time for the earliest event,
    215217        // process messages using WaitForMessages. Whenever this funtion times out,
     
    222224            // only the scheduling latency).
    223225
    224226            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());
    227                 is_realtime = false;
    228                 break;
    229             }
    230             if (fRealTimeQueue.HasEvents() && (TimeSource()->RealTime() - fSchedulingLatency) >= fRealTimeQueue.FirstEventTime()) {
    231                 latency = fSchedulingLatency;
    232                 is_realtime = true;
    233                 break;
    234             }
    235227            waituntil = B_INFINITE_TIMEOUT;
    236228            if (fEventQueue.HasEvents()) {
    237                 waituntil = TimeSource()->RealTimeFor(fEventQueue.FirstEventTime(), latency);
    238 //              printf("node %02d waiting for %12Ld that will happen at %12Ld\n", ID(), fEventQueue.FirstEventTime(), waituntil);
     229                const media_timed_event *firstEvent = fEventQueue.FirstEvent();
     230                waituntil = TimeSource()->RealTimeFor(firstEvent->event_time, latency);
    239231                is_realtime = false;
     232                lateness = firstEvent->queued_time - waituntil;
     233                if (lateness > 0) {
     234//                  if (lateness > 1000)
     235//                      printf("node %02ld handling %12Ld at %12Ld -- %Ld late,  queued at %Ld now %12Ld \n",
     236//                          ID(), fEventQueue.FirstEventTime(), TimeSource()->Now(), lateness,
     237//                          firstEvent->queued_time, TimeSource()->RealTime());
     238                    is_realtime = false;
     239                    break;
     240                }
     241//              printf("node %02ld waiting for %12Ld that will happen at %12Ld\n", ID(), fEventQueue.FirstEventTime(), waituntil);
    240242            }
    241243            if (fRealTimeQueue.HasEvents()) {
     244                const media_timed_event *firstEvent = fRealTimeQueue.FirstEvent();
    242245                bigtime_t temp;
    243                 temp = fRealTimeQueue.FirstEventTime() - fSchedulingLatency;
     246                temp = firstEvent->event_time - fSchedulingLatency;
     247                lateness =  firstEvent->queued_time - temp;
     248                if (lateness > 0) {
     249                    is_realtime = true;
     250                    break;
     251                }
    244252                if (temp < waituntil) {
    245253                    waituntil = temp;
    246254                    is_realtime = true;
    247                     latency = fSchedulingLatency;
    248255                }
    249256            }
     257            lateness = 0;   // remove any extraneous value if we get this far
    250258            err = WaitForMessage(waituntil);
    251259            if (err == B_TIMED_OUT)
    252260                break;
     
    258266        else
    259267            err = fEventQueue.RemoveFirstEvent(&event);
    260268
    261 //      printf("node %02d handling    %12Ld  at %12Ld\n", ID(), event.event_time, system_time());
     269//      printf("node %02ld handling  %12Ld  at %12Ld\n", ID(), event.event_time, TimeSource()->Now());
    262270
    263         if (err == B_OK) {
    264             bigtime_t lateness;
    265             if (is_realtime)
    266                 lateness = TimeSource()->RealTime() - event.event_time;
    267             else
    268                 lateness = TimeSource()->RealTime() - TimeSource()->RealTimeFor(event.event_time, 0) + fEventLatency;
    269             DispatchEvent(&event, lateness, is_realtime);
    270         }
     271        if (err == B_OK) DispatchEvent(&event, lateness, is_realtime);
    271272    }
    272273}
    273274
     
    388389        latency = 0;
    389390
    390391    fEventLatency = latency;
     392    write_port_etc(ControlPort(), GENERAL_PURPOSE_WAKEUP, 0, 0, B_TIMEOUT, 0);
    391393}
    392394
    393395
  • src/kits/media/MediaNode.cpp

     
    377377    TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n",
    378378        message, fNodeID, this);
    379379
     380    if (message == GENERAL_PURPOSE_WAKEUP) return B_OK; // no action needed
     381
    380382    if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) {
    381383        TRACE("BMediaNode::WaitForMessage calling BMediaNode\n");
    382384        if (B_OK == BMediaNode::HandleMessage(message, data, size))
  • src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp

     
    11/*
    22 * Copyright 2002 David Shipman,
    33 * Copyright 2003-2007 Marcus Overhagen
    4  * Copyright 2007-2010 Haiku Inc. All rights reserved.
     4 * Copyright 2007-2011 Haiku Inc. All rights reserved.
    55 *
    66 * Distributed under the terms of the MIT License.
    77 */
     
    108108    fDownstreamLatency(1),
    109109    fInternalLatency(1),
    110110    fDisableStop(false),
    111     fLastLateNotification(0)
     111    fLastLateNotification(0),
     112    fLastLateness(0)
    112113{
    113114    BMediaNode::AddNodeKind(B_SYSTEM_MIXER);
    114115
     
    314315void
    315316AudioMixer::HandleInputBuffer(BBuffer* buffer, bigtime_t lateness)
    316317{
    317     if (lateness > kMaxJitter) {
    318         debug_printf("Received buffer %Ld usec late\n", lateness);
     318    if (lateness > kMaxJitter && lateness > fLastLateness) {
     319        debug_printf("AudioMixer: Dequeued input buffer %Ld usec late\n", lateness);
    319320        if (RunMode() == B_DROP_DATA || RunMode() == B_DECREASE_PRECISION
    320321            || RunMode() == B_INCREASE_LATENCY) {
    321             debug_printf("sending notify\n");
     322            debug_printf("AudioMixer: sending notify\n");
    322323
    323324            // Build a media_source out of the header data
    324325            media_source source = media_source::null;
     
    328329            NotifyLateProducer(source, lateness, TimeSource()->Now());
    329330
    330331            if (RunMode() == B_DROP_DATA) {
    331                 debug_printf("dropping buffer\n");
     332                debug_printf("AudioMixer: dropping buffer\n");
    332333                return;
    333334            }
    334335        }
    335336    }
     337    fLastLateness = lateness;
    336338
    337     //  printf("Received buffer with lateness %Ld\n", lateness);
    338 
    339339    fCore->Lock();
    340340    fCore->BufferReceived(buffer, lateness);
    341341    fCore->Unlock();
     
    10011001
    10021002    if (what == fCore->Output()->MediaOutput().source
    10031003        && RunMode() == B_INCREASE_LATENCY) {
    1004         // We need to ignore subsequent notices whose performance time
    1005         // lies before the performance time of the last notification
     1004        // We need to ignore subsequent notices whose arrival time here
     1005        // lies within the last lateness, because queued-up buffers will all be 'late'
    10061006        if (performanceTime < fLastLateNotification)
    10071007            return;
    10081008
    10091009        fInternalLatency += howMuch;
    10101010
    10111011        // At some point a too large latency can get annoying
     1012        // (actually more than annoying, as there won't be enough buffers long before this!)
    10121013        if (fInternalLatency > kMaxLatency)
    10131014            fInternalLatency = kMaxLatency;
    10141015
    1015         fLastLateNotification = TimeSource()->Now();
     1016        fLastLateNotification = TimeSource()->Now() + howMuch;
    10161017
    10171018        debug_printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
    10181019        SetEventLatency(fDownstreamLatency + fInternalLatency);
  • src/add-ons/media/media-add-ons/mixer/AudioMixer.h

     
    136136            bool                fDisableStop;
    137137            media_format        fDefaultFormat;
    138138            bigtime_t           fLastLateNotification;
     139            bigtime_t           fLastLateness;
    139140};
    140141
    141142