How to multicast H.264/SVC video over wired networks?

 

[To Read before running this example]

  Please refer to How to do H.264 SVC simulations? first. . If you use this work, please add the following into your reference.

 

C. H. Ke, " myEvalSVC: an Integrated Simulation Framework for Evaluation of H.264/SVC Transmission ", KSII Transactions on Internet and Information Systems, vol. 6, no. 1, pp. 378-393, Jan. 2012 (SCI)

 

[Preparation]

To modify two files.

a. Modify the myevalsvc.cc that is under /ns-allinone-2.29/ns-2.29/myvideo

 

void myEvalSVC::timeout()

{

 …………………..

if(x_ > 0){

          for(i=0 ; i<x_; i++)

              agent_->sendmsg(max_);

        }

               

        if(y_!=0)

          agent_->sendmsg(y_);

……………………

          }

   

   b. Modify the myevalsvc_sink.cc that is under /ns-allinone-2.29/ns-2.29/myvideo

 

      fprintf(tFile,"%-16f %-16d %-16d %-16d %-16d %-16d %-16d %-16f\n", Scheduler::instance().clock(), hdr->svc_frameno, hdr->size(), hdr->svc_lid, hdr->svc_tid, hdr->svc_qid, rh->seqno(), hdr->svc_sendtime);

 

(P.S. The models for wired node and wireless node are different. So remember one thing. If the simulated environment is wireless network, hdr->size()-20 is adopted. If wired network, no need to remove 20 from the packet size).

 

[Simulation] 

In this simple example, there are 4 nodes. Node0 connects to Node1. Then Node1 connects to Node2, Node3, and Node4 respectively. The encoded H.264/SVC video is encoded using Temporal Scalability feature. The encoded video contains one base layer (TID=0) and two enhancement layers (TID=1 and TID=2). Please refer to How to do H.264 SVC simulations? for encoding process. The base layer (TID=0) is transmitted by multicast group0 and received by Node2, Node 3, and Node 4. The enhancement layer (TID=1) is transmitted by multicast group1 and received by Node2 and Node3. The enhancement layer (TID=2) is transmitted by multicast group2 and received only by Node2.

 

1.     Using the following split_tid.awk file to split the original ns2send trace file to three files. (For TID=0, TID=1, TID=2 trace files)

BEGIN{

}

{

  sendtime=$1;

  framesize=$2;

  lid=$3;

  tid=$4;

  qid=$5;

  nopkt=$6;

  if($4==T)

    printf("%s\t%s\t%s\t%s\t%s\t%s\n",$1,$2,$3,$4,$5,$6)

}

END{

}

1

2.     The NS2 simulation script (test_svc_multicast3.tcl)

set ns [new Simulator -multicast on]

set group0 [Node allocaddr]

set group1 [Node allocaddr]

set group2 [Node allocaddr]

 

set f [open out.tr w]

$ns trace-all $f

proc finish {} {

       global ns f

       $ns flush-trace

       puts "Simulation completed."

       close $f

       exit 0

}

 

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

set n3 [$ns node]

set n4 [$ns node]

 

$ns duplex-link $n0 $n1 10Mb 1ms DropTail

$ns duplex-link $n1 $n2 10Mb 1ms DropTail

$ns duplex-link $n1 $n3 10Mb 1ms DropTail

$ns duplex-link $n1 $n4 10Mb 1ms DropTail

 

set max_fragmented_size 1500

set packetSize [expr $max_fragmented_size+20]

 

set src_udp1 [new Agent/my_UDP]

$src_udp1 set dst_addr_ $group0

$src_udp1 set dst_port_ 100

$src_udp1 set_filename sd_f0

$src_udp1 set packetSize_ $packetSize

$ns attach-agent $n0 $src_udp1

 

set dst2_f0 [new Agent/myEvalSVC_Sink]

$dst2_f0 set_filename rd_n2_f0

$n2 attach $dst2_f0 100

 

set dst3_f0 [new Agent/myEvalSVC_Sink]

$dst3_f0 set_filename rd_n3_f0

$n3 attach $dst3_f0 100

 

set dst4_f0 [new Agent/myEvalSVC_Sink]

$dst4_f0 set_filename rd_n4_f0

$n4 attach $dst4_f0 100

 

set original_file_name ns2send_tid0

set trace_file_name video1.dat

set original_file_id [open $original_file_name r]

set trace_file_id [open $trace_file_name w]

 

set pre_time 0

 

while {[eof $original_file_id] == 0} {

    gets $original_file_id current_line

     

    scan $current_line "%f%d%d%d%d%d" t_ size_ lid_ tid_ qid_ fno_

    set time [expr int(($t_ - $pre_time)*1000000.0)]

   

    if { $tid_ == 0 } {

      set prio_p 1

    }

   

    if { $tid_ == 1 } {

      set prio_p 1

    }

   

    if { $tid_ == 2 } {

      set prio_p 1

    }

   

    puts  $trace_file_id "$time $size_ $lid_ $tid_ $qid_ $fno_ $prio_p $max_fragmented_size"

    set pre_time $t_

}

 

close $original_file_id

close $trace_file_id

 

set trace_file [new Tracefile]

$trace_file filename $trace_file_name

set video1 [new Application/Traffic/myEvalSVC]

$video1 attach-agent $src_udp1

$video1 attach-tracefile $trace_file

 

set src_udp2 [new Agent/my_UDP]

$src_udp2 set dst_addr_ $group1

$src_udp2 set dst_port_ 110

$src_udp2 set_filename sd_f1

$src_udp2 set packetSize_ $packetSize

$ns attach-agent $n0 $src_udp2

 

set dst2_f1 [new Agent/myEvalSVC_Sink]

$dst2_f1 set_filename rd_n2_f1

$n2 attach $dst2_f0 110

 

set dst3_f1 [new Agent/myEvalSVC_Sink]

$dst3_f1 set_filename rd_n3_f1

$n3 attach $dst3_f1 110

 

set original_file_name2 ns2send_tid1

set trace_file_name2 video2.dat

set original_file_id2 [open $original_file_name2 r]

set trace_file_id2 [open $trace_file_name2 w]

 

set pre_time2 0

 

while {[eof $original_file_id2] == 0} {

    gets $original_file_id2 current_line

    

    scan $current_line "%f%d%d%d%d%d" t_ size_ lid_ tid_ qid_ fno_

    set time [expr int(($t_ - $pre_time2)*1000000.0)]

   

    if { $tid_ == 0 } {

      set prio_p 1

    }

   

    if { $tid_ == 1 } {

      set prio_p 1

    }

   

    if { $tid_ == 2 } {

      set prio_p 1

    }

   

    puts  $trace_file_id2 "$time $size_ $lid_ $tid_ $qid_ $fno_ $prio_p $max_fragmented_size"

    set pre_time2 $t_

}

 

close $original_file_id2

close $trace_file_id2

 

set trace_file2 [new Tracefile]

$trace_file2 filename $trace_file_name2

set video2 [new Application/Traffic/myEvalSVC]

$video2 attach-agent $src_udp2

$video2 attach-tracefile $trace_file2

 

set src_udp3 [new Agent/my_UDP]

$src_udp3 set dst_addr_ $group2

$src_udp3 set dst_port_ 111

$src_udp3 set_filename sd_f2

$src_udp3 set packetSize_ $packetSize

$ns attach-agent $n0 $src_udp3

 

set dst2_f2 [new Agent/myEvalSVC_Sink]

$dst2_f2 set_filename rd_n2_f2

$n2 attach $dst2_f2 111

 

set original_file_name3 ns2send_tid2

set trace_file_name3 video3.dat

set original_file_id3 [open $original_file_name3 r]

set trace_file_id3 [open $trace_file_name3 w]

 

set pre_time3 0

 

while {[eof $original_file_id3] == 0} {

    gets $original_file_id3 current_line

    

    scan $current_line "%f%d%d%d%d%d" t_ size_ lid_ tid_ qid_ fno_

    set time [expr int(($t_ - $pre_time3)*1000000.0)]

   

    if { $tid_ == 0 } {

      set prio_p 1

    }

   

    if { $tid_ == 1 } {

      set prio_p 1

    }

   

    if { $tid_ == 2 } {

      set prio_p 1

    }

   

    puts  $trace_file_id3 "$time $size_ $lid_ $tid_ $qid_ $fno_ $prio_p $max_fragmented_size"

    set pre_time3 $t_

}

 

close $original_file_id3

close $trace_file_id3

 

set trace_file3 [new Tracefile]

$trace_file3 filename $trace_file_name3

set video3 [new Application/Traffic/myEvalSVC]

$video3 attach-agent $src_udp3

$video3 attach-tracefile $trace_file3

 

set mproto DM

set mrthandle [$ns mrtproto $mproto]

 

$ns at 0  "$n2 join-group  $dst2_f0 $group0"

$ns at 0  "$n3 join-group  $dst3_f0 $group0"

$ns at 0  "$n4 join-group  $dst4_f0 $group0"

$ns at 0  "$n2 join-group  $dst2_f1 $group1"

$ns at 0  "$n3 join-group  $dst3_f1 $group1"

$ns at 0  "$n2 join-group  $dst2_f2 $group2"

$ns at 50 "$n2 leave-group $dst2_f0 $group0"

$ns at 50 "$n2 leave-group $dst3_f0 $group0"

$ns at 50 "$n2 leave-group $dst4_f0 $group0"

$ns at 50 "$n2 leave-group $dst2_f1 $group1"

$ns at 50 "$n2 leave-group $dst3_f1 $group1"

$ns at 50 "$n2 leave-group $dst2_f2 $group2"

$ns at 1.0  "$video1 start"

$ns at 40.0 "$video1 stop"

$ns at 1.0  "$video2 start"

$ns at 40.0 "$video2 stop"

$ns at 1.0  "$video3 start"

$ns at 40.0 "$video3 stop"

$ns at 55.0 "finish"

$ns run

$ns test_svc_multicast3.tcl

3.     After simulation, you can get rd_n2_f0, rd_n2_f1, rd_n2_f2 three receiver trace files for Node2; rd_n3_f0, rd_n3_f1 for Node 3; and rd_n4_f0 for Node 4.

Let’s start by evaluating the received video quality for Node2.

a.     Combine three received trace files into one file.

$cat  rd_n2_f0  rd_n2_f1  rd_n2_f2  > rd_n2

b.      Convert the rd file to the format required for SVEF file.

$ awk  f  prepare_receivedtrace1.awk rd_n2 > ns2received

$ ./prepare_receivedtrace2.exe ns2send ns2received temporal_originaltrace-frameno.txt > received.txt

c.      Change to cygwin_new environment to do the post-processing for delivered video quality evaluation.

$nalufilter temporal_originaltrace-frameno.txt received.txt 5000 30 > filteredtrace.txt

$BitStreamExtractorStatic.exe temporal.264 temporal-filter.264 –et filteredtrace.txt

$H264AVCDecoderLibTestStatic.exe temporal-filter.264 temporal-filter.yuv

$framefilter filteredtrace.txt 152064 300 temporal-filter.yuv temporal-conceal.yuv

$PSNRStatic.exe  352  288  foreman_cif  temporal-conceal.yuv

You can get the average PSNR for Node2 is 35.9.

d.    With the same steps, you can evaluate the received quality for Node 3 and Node 4.

 

Last modified: 2012/02/02

 

Contact Information

Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Taiwan

Email: smallko@gmail.com