Subject: [rohc] questions on field_scaling

From: Thomas Lefort <[email-masked]>
Date: Fri, 07 Dec 2007 19:27:55 +0100

Hi everybody,

I'm having trouble understanding the field_scaling method from ROHCv2:

field_scaling(stride_value, scaled_value, unscaled_value)
 {
   UNCOMPRESSED {
     residue_field [ 32 ];
   }

   COMPRESSED no_scaling {
     ENFORCE(stride_value == 0);
     ENFORCE(residue_field.UVALUE == unscaled_value);
     ENFORCE(scaled_value == 0);
   }

   COMPRESSED scaling_used {
     ENFORCE(stride_value != 0);
     ENFORCE(residue_field.UVALUE == (unscaled_value % stride_value));
     ENFORCE(unscaled_value == scaled_value * stride_value + 
residue_field.UVALUE);
   }
 }

As a case study, here is a simplified excerpt from the rtp_baseheader 
method:

   UNCOMPRESSED v6 {
     // ...
     timestamp                                          [  32 ];
     // ...
   }

   CONTROL {
     ENFORCE(ts_stride.UVALUE == ts_stride_value);
     ts_stride                           [ 32 ];
     ts_scaled                           [ 32 ];
     ts_offset =:= field_scaling(ts_stride.UVALUE, ts_scaled.UVALUE, 
timestamp.UVALUE) [ 32 ];
   }

   COMPRESSED co_common {
     // ...
     ts_scaled =:= some_encoding(...);
     // ...
   }

As I read it, when scaling is used, the compressor will assign 
residue_field (ts_offset) its UVALUE, then derive scaled_value 
(ts_scaled.UVALUE) from the following rewriting:

  ENFORCE(scaled_value == (unscaled_value - residue_field.UVALUE) / 
stride_value);

Then the decompressor will want to reconstruct unscaled_value 
(timestamp). The third assertion in the scaling_used format tells us 
that unscaled_value can be derived from residue_field; however, the 
second one tells us just the converse, and residue_field is still 
unknown. What is the decompressor supposed to do ?

I found some hints in the current draft (revision 2) §6.6.8:

 > Once the value of the scaling factor is established, before using the 
new scaling factor, the compressor must have enough confidence that the 
decompressor has successfully calculated the residue (ts_offset) of the 
scaling function for the timestamp. This is done by sending unscaled 
timestamp values to allow the decompressor to establish the residue 
based on the current ts_stride.

This text strongly suggests that ts_offset is part of the decompressor 
context. However it is formally defined as a local control field, so how 
does it persist between packets ? Is there an implicit relationship 
between control fields and the context ? What happens if the method is 
used several times per packet ?

Moreover, if §6.6.8 is actually implemented by the field_scaling method 
as used above, how can I formally distinguish between updating the 
context and just checking its value against an assertion ?

Thank you for discussing this.

-- Thomas Lefort, software engineer at ENST Bretagne

_______________________________________________
Rohc mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/rohc

---

From: "Kristofer Sandlund" <[email-masked]>
Date: Mon, 10 Dec 2007 16:24:40 +0100

Hi Thomas,

this has already been discussed as part of Carl Knutssons CDR
review (see mails to this list from November). In my local version
of the profiles, ts_offset is a global control field.
We'll be submitting a new draft soon containing this change and
all other last-call comments.

/Kristofer

Thomas Lefort <mailto:[email-masked]> wrote on den 7 december 2007 19:28 :

> field_scaling(stride_value, scaled_value, unscaled_value)  {
>    UNCOMPRESSED {
>      residue_field [ 32 ];
>    }
> 
>    COMPRESSED no_scaling {
>    residue_field.UVALUE); }
>    // ... }
>    timestamp.UVALUE) [ 32 ]; }
> 
>    COMPRESSED co_common {
>      // ...
> decompressor has successfully calculated the residue (ts_offset) of
> the scaling function for the timestamp. This is done by sending
> unscaled timestamp values to allow the decompressor to establish the
> residue based on the current ts_stride.
>

---

From: Thomas Lefort <[email-masked]>
Date: Tue, 11 Dec 2007 17:11:02 +0100

Carl Knutsson wrote:
 > 19) Maybe we should consider making ts_offset, ts_stride and
 >    time_stride global. To be in scope for both rtp() and
 >    rtp_base_header. Otherwise co_common must be sent after initial IR
 > sequence.

My understanding of this is that global control fields persist across 
packets, and are part of the compressor and decompressor context. This 
seems necessary for the field_scaling method to succeed at decompression 
when scaling is used. However, this is only my assumption, as I couldn't 
find an explicit spec passage about this issue; what do you think ?

Please note the same mechanism is used in ROHC-TCP (RFC 4996) to encode 
seq_number_residue and ack_number_residue, so you'll probably want to 
update it too.

---

From: "Kristofer Sandlund" <[email-masked]>
Date: Wed, 12 Dec 2007 09:51:11 +0100

Thomas Lefort <mailto:[email-masked]> wrote on
den 11 december 2007 17:11 :

>  >    rtp_base_header. Otherwise co_common must be sent after initial
>  IR > sequence.
> 
> seems necessary for the field_scaling method to succeed at
> decompression when scaling is used. However, this is only my
> assumption, as 
> I couldn't

I do not understand your question. Check RFC4997 (the FN spec) to
see the meaning of global scopes vs. local scopes.

> seq_number_residue and ack_number_residue, so you'll probably want to

Yes, I'm aware of that. There are some issues with 4996.

/k

---

From: Carl Knutsson <[email-masked]>
Date: Wed, 12 Dec 2007 10:00:24 +0100

Jag gissar att han vill att ts_offset ska default encodas till static.
Så att det uttryckligen står att använd ts_offset uträknat från
föregående paket. Han tror att globala control fält sparas i
decompressorn mellan paket. Jag kan inte heller hitta något om detta i
FN specen.

/Calle

---

From: Carl Knutsson <[email-masked]>
Date: Wed, 12 Dec 2007 10:06:43 +0100

Hi all,

I am sorry about that. It was meant to Kristofer only. We are both
swedish :)

Cheers,

/Calle