A prototype for H.264 evaluation framework using NS2

 

      This work is done with aid of Juli OROZCO. He provided me the parser and error insertion program source codes for H.264 stream file. But the codes he provides work on Sun. Therefore, I have to modify these codes to make them work on cygwin platform. The H.264 codec I used is JM 1.7. It can be downloaded from http://bs.hhi.de/~suehring/tml/. The newer version of JM doesn’t support packet losses. (This means that when I remove some parts of compressed file if those packets are lost during transmission, the distorted file can not be decoded.) So JM 1.7 is used to encode and decode video sequences. The whole evaluation framework can be downloaded from here.

 

[Preparation-Intall my module into NS2]

1.      Download the YUV format video sequences from QCIF or CIF. (In order to test the framework, please download the foreman_cif.yuv.)

 

2.      Modify packet.h in the common folder (~/common/packet.h).

 

struct hdr_cmn {

  enum dir_t { DOWN= -1, NONE= 0, UP= 1 };

  packet_t ptype_;      // packet type (see above)

  int     size_;                // simulated packet size

  int     uid_;         // unique id

  int     error_;              // error flag

  int     errbitcnt_;     // # of corrupted bits jahn

  int     fecsize_;

  double      ts_;           // timestamp: for q-delay measurement

  int     iface_;              // receiving interface (label)

  dir_t direction_;        // direction: 0=none, 1=up, -1=down

  // source routing

        char src_rt_valid;

  double ts_arr_; // Required by Marker of JOBS

 //add the following three lines

  int frametype_;               // frame type

  double sendtime_;  // send time

  unsigned long int frame_pkt_id_;

 

3.      Modify agent.h in the common folder (~/common/agent.h).

 

class Agent : public Connector {

 public:

  Agent(packet_t pktType);

  virtual ~Agent();

  void recv(Packet*, Handler*);

 

......

inline packet_t get_pkttype() { return type_; }

// add the following two lines

  inline void set_frametype(int type) { frametype_ = type; }

  inline void set_prio(int prio) { prio_ = prio; } 

 

 protected:

  int command(int argc, const char*const* argv);

 

......

  int defttl_;                        // default ttl for outgoing pkts

 // add the following line

  int frametype_;                // frame type for MPEG video transmission

 

......

 private:

  void flushAVar(TracedVar *v);

};

 

4.      Modify agent.cc in the common folder (~/common/agent.cc).

 

Agent::Agent(packet_t pkttype) :

  size_(0), type_(pkttype), frametype_(0),

  channel_(0), traceName_(NULL),

  oldValueList_(NULL), app_(0), et_(0)

{

}

 

......

Agent::initpkt(Packet* p) const

{

  hdr_cmn* ch = hdr_cmn::access(p);

  ch->uid() = uidcnt_++;

  ch->ptype() = type_;

  ch->size() = size_;

  ch->timestamp() = Scheduler::instance().clock();

  ch->iface() = UNKN_IFACE.value(); // from packet.h (agent is local)

  ch->direction() = hdr_cmn::NONE;

 

  ch->error() = 0;        /* pkt not corrupt to start with */

 // add the following line

  ch->frametype_= frametype_;

......

 

5.      Create a “myh264” folder under ns and put myudp.cc, myudp.h, myudpsink3.cc, myudpsink3.h, and mytraffictrace3.cc in it.

 

6.      Modify the file tcl/lib/ns-default.tcl (~ns/tcl/lib/ns-default.tcl).

#Add the following two lines

Agent/myUDP set packetSize_ 1000

Tracefile set debug_ 0

 

7.      Modify Makefile

Put myh264/myudp.o, myh264/myudpsink3.o and myh264/mytraffictrace3.o in the OBJ_CC list.

 

8.      Recompilation.

make clean; make

 

[Example]

1.      Encode the Foreman_cif.yuv. (encoder.cfg is needed to be at the same folder with lencode.exe)

$./lencode.exe

   After encoding, you will get a compressed file named foreman_cif.264.

 

2.      Parse the compressed file. (config is needed to be at the same folder with parser.exe)

$./parser.exe config

Ater parsing, you will get a result file named foreman_cif.txt.

 

3.      Run the test tcl file (be.tcl).

$ns.exe be.tcl

After running the simulation, you will get sd_be (sender trace file) and rd_be (receiver trace file). These two files are used to identify which packets are lost.

 

4.      Run the error insertion program.

$./errinsert.exe    foreman_cif.264       distorted.264    sd_be       rd_be

After running the error insertion program, you will get a distorted h.264 file named distorted.264.

 

5.      Decode the distorted.264. (decoder_distorted.cfg is needed to be at the same folder with ldecod.exe)

$./ldecod.exe decoder_distorted.cfg

After decoding, you will get foreman_cif_distorted.yuv.

 

6.      Finally you can get the PSNR value if you compare the foreman_cif.yuv and foreman_cif_distorted.yuv.

$./psnr.exe  352  288  420  foreman_cif.yuv        foreman_cif_distorted.yuv

 

p.s. One phd student in NTU told me that the codec I use is H.26L, not H.264.

 

Last modified: 2006/05/02

 

Author : Chih-Heng, Ke

Website: http://csie.nqu.edu.tw/smallko

Email: smallko@ee.ncku.edu.tw

Phd candidate, EE Department, NCKU, Taiwan