Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #include "media_clock_converter.h"
     19 
     20 // Use default DLL entry point for Symbian
     21 #include "oscl_dll.h"
     22 OSCL_DLL_ENTRY_POINT_DEFAULT()
     23 
     24 // All the rounding in this utility is using method rounding up
     25 // For example, normal calculation
     26 //   A / B
     27 // is replaced as
     28 //   (A + (B - 1))/ B
     29 // In an average roudning up is same as rounding down, but it resolve some issue
     30 
     31 //////////////////////////////////////////////////////////////////////////////////
     32 OSCL_EXPORT_REF void MediaClockConverter::set_value(const MediaClockConverter& src)
     33 {
     34     // Timescale value cannot be zero
     35     OSCL_ASSERT(src.get_timescale() != 0);
     36     if (src.get_timescale() == 0)
     37     {
     38         OSCL_LEAVE(OsclErrCorrupt);
     39     }
     40 
     41     OSCL_ASSERT(timescale != 0);
     42     if (0 == timescale)
     43     {
     44         OSCL_LEAVE(OsclErrCorrupt);
     45     }
     46 
     47     uint64 value = (uint64(src.get_wrap_count())) << 32;
     48 
     49     value += src.get_current_timestamp();
     50 
     51     // rounding up
     52     value = (uint64(value) * timescale + uint64(src.get_timescale() - 1)) / src.get_timescale();
     53 
     54     wrap_count = ((uint32)(value >> 32)) % timescale;
     55 
     56     current_ts = (uint32)(value & 0xFFFFFFFF);
     57 }
     58 
     59 //////////////////////////////////////////////////////////////////////////////////
     60 OSCL_EXPORT_REF void MediaClockConverter::set_timescale(uint32 new_timescale)
     61 {
     62     // Timescale value cannot be zero
     63     OSCL_ASSERT(new_timescale != 0);
     64     if (0 == new_timescale)
     65     {
     66         OSCL_LEAVE(OsclErrArgument);
     67     }
     68 
     69     OSCL_ASSERT(timescale != 0);
     70     if (0 == timescale)
     71     {
     72         OSCL_LEAVE(OsclErrCorrupt);
     73     }
     74 
     75     uint64 value = ((uint64)wrap_count) << 32;
     76     value += current_ts;
     77 
     78     // rounding up
     79     value = (value * new_timescale + uint64(timescale - 1)) / timescale;
     80 
     81     timescale = new_timescale;
     82 
     83     wrap_count = ((uint32)(value >> 32)) % timescale;
     84 
     85     current_ts = (uint32)(value & 0xFFFFFFFF);
     86 }
     87 
     88 //////////////////////////////////////////////////////////////////////////////////
     89 OSCL_EXPORT_REF void MediaClockConverter::set_clock_other_timescale(uint32 value,
     90         uint32 in_timescale)
     91 {
     92     // Timescale value cannot be zero
     93     OSCL_ASSERT(in_timescale != 0);
     94     if (0 == in_timescale)
     95     {
     96         OSCL_LEAVE(OsclErrArgument);
     97     }
     98 
     99     OSCL_ASSERT(timescale != 0);
    100     if (0 == timescale)
    101     {
    102         OSCL_LEAVE(OsclErrCorrupt);
    103     }
    104 
    105     uint64 new_value = (uint64)value * timescale;
    106     uint64 in_timescale64Comp = (uint64)(in_timescale - 1);
    107 
    108     // rounding up
    109     new_value = new_value + in_timescale64Comp ;
    110     new_value /= in_timescale;
    111 
    112     wrap_count = ((uint32)(new_value >> 32)) % timescale;
    113 
    114     current_ts = (uint32)(new_value & 0xFFFFFFFF);
    115 }
    116 
    117 //////////////////////////////////////////////////////////////////////////////////
    118 OSCL_EXPORT_REF uint32 MediaClockConverter::get_timediff_and_update_clock(uint32 value,
    119         uint32 in_timescale,
    120         uint32 output_timescale)
    121 {
    122     // Timescale value cannot be zero
    123     OSCL_ASSERT(in_timescale != 0);
    124     if (0 == in_timescale)
    125     {
    126         OSCL_LEAVE(OsclErrArgument);
    127     }
    128 
    129     // convert to native timescale
    130     // rounding up
    131     uint64 new_value = (uint64)value * timescale + uint64(in_timescale - 1);
    132     new_value /= in_timescale;
    133 
    134     uint32 new_timevalue = ((uint32)(new_value & 0xFFFFFFFF));
    135 
    136     return get_timediff_and_update_clock(new_timevalue, output_timescale);
    137 
    138 }
    139 
    140 //////////////////////////////////////////////////////////////////////////////////
    141 OSCL_EXPORT_REF uint32 MediaClockConverter::get_timediff_and_update_clock(uint32 value,
    142         uint32 output_timescale)
    143 {
    144     // Timescale value cannot be zero
    145     OSCL_ASSERT(timescale != 0);
    146     if (0 == timescale)
    147     {
    148         OSCL_LEAVE(OsclErrCorrupt);
    149     }
    150 
    151     uint32 diff = value - current_ts;
    152 
    153     // convert to output timescale
    154     // rounding up
    155     uint64 new_value = (uint64)diff * output_timescale + uint64(timescale - 1);
    156     new_value /= timescale;
    157 
    158     diff = ((uint32)(new_value & 0xFFFFFFFF));
    159 
    160     if (update_clock(value))
    161     {
    162         return diff;
    163     }
    164 
    165     return 0;
    166 }
    167 
    168 
    169 //////////////////////////////////////////////////////////////////////////////////
    170 OSCL_EXPORT_REF bool MediaClockConverter::update_clock(uint32 new_ts)
    171 {
    172     uint32 diff = new_ts - current_ts;
    173     if (new_ts < current_ts)
    174     {
    175         if (diff < WRAP_THRESHOLD)
    176         {
    177             if (++wrap_count >= timescale)
    178             {
    179                 wrap_count = 0;
    180             }
    181             current_ts = new_ts;
    182             return true;
    183         }
    184         // otherwise this an earlier value so ignore it.
    185     }
    186     else
    187     {
    188         if (diff < MISORDER_THRESHOLD)
    189         {
    190             current_ts = new_ts;
    191             return true;
    192         }
    193         // otherwise this an earlier value so ignore it.
    194     }
    195     return false;
    196 }
    197 
    198 //////////////////////////////////////////////////////////////////////////////////
    199 OSCL_EXPORT_REF uint32 MediaClockConverter::get_converted_ts(uint32 new_timescale) const
    200 {
    201     // Timescale value cannot be zero
    202     OSCL_ASSERT(timescale != 0);
    203     if (0 == timescale)
    204     {
    205         OSCL_LEAVE(OsclErrCorrupt);
    206     }
    207 
    208     uint64 value = ((uint64)wrap_count) << 32;
    209     // rounding up
    210     value = ((value + uint64(current_ts)) * uint64(new_timescale) + uint64(timescale - 1)) / uint64(timescale);
    211 
    212     return ((uint32) value);
    213 
    214 }
    215