Statistics
| Branch: | Revision:

psnr-tools / psnr.sh @ 59ff2bd4

History | View | Annotate | Download (6.26 KB)

1
#!/bin/bash
2
 ###########################################
3
 #  Copyright (c) 2009 Csaba Kiraly        #
4
 #                                         #
5
 #  This is free software; see gpl-3.0.txt #
6
 ###########################################
7

    
8
[[ $PSNR_TOOLS ]] || { echo "\$PSNR_TOOLS not defined"; exit 1; }
9
[[ $PSNR_TMPPREFIX ]] || { echo "\$PSNR_TMPPREFIX not defined"; exit 1; }
10
[[ $FFMPEG ]] || { echo "\$FFMPEG not defined"; exit 1; }
11

    
12
mkdir -p `dirname ${PSNR_TMPPREFIX}_`
13

    
14
ORIG_YUV=${PSNR_TMPPREFIX}orig.yuv
15
ORIG_YUV_DESC=${ORIG_YUV}.desc
16
ORIG_MP4=${PSNR_TMPPREFIX}orig_compressed.m4v
17
RECEIVED_MP4=${PSNR_TMPPREFIX}received.m4v
18
REFILLED_YUV=${PSNR_TMPPREFIX}refilled.yuv
19

    
20
ANALYSER=$PSNR_TOOLS/Analyser/analyser
21
CHUNKER=$PSNR_TOOLS/Chunker/chunker
22
CUTTER=$PSNR_TOOLS/Cutter/cutter
23
LOSTFRAMES=$PSNR_TOOLS/LostFrames/lf
24
LOGPARSER=$PSNR_TOOLS/LogParser/logparser
25
REFILLER=$PSNR_TOOLS/ReFiller/refiller
26
EVALPSNR=$PSNR_TOOLS/EvalVid/psnr
27

    
28

    
29
function usage {
30
   echo "Usage: $0 init <orig video> <codec settings>";
31
   echo "       $0 chunk <chunkmode> <chunksize>";
32
   echo "       $0 calc <chunkmode>  <chunksize> <file with losses>";
33
   echo "       $0 play <chunkmode>  <chunksize> <file with losses>";
34
   echo "examples:";
35
   echo " $0 init ~/video/foreman_cif_100GOP.yuv '-f h264 -vcodec libx264 -vpre libx264-default -keyint_min 12  -g 12 -b 0.4M '";
36
   echo " $0 calc 0 lost.txt";
37
   echo " $0 play 1500 lost.txt";
38
   echo "";
39
   exit $1 
40
}
41

    
42
function init {
43
  [[ $# -eq 2 ]] || usage 1
44

    
45
  ORIG=$1 # the original sequence. Can be a YUV but also a something encoded. If it is a YUV, you need a .desc file as well!!!
46
  ORIG_DESC=${ORIG}.desc
47
  CODER=$2 # conversion parameters for streaming
48

    
49
  #initialize by creating YUV, if needed
50
  rm $ORIG_YUV $ORIG_YUV_DESC
51
  if [[ $ORIG =~ \.[yY][uU][vV]$ ]]; then #if it is aready a YUV, just link or copy
52
    ln -s  $ORIG $ORIG_YUV || cp $ORIG $ORIG_YUV
53
    ln -s  $ORIG_DESC $ORIG_YUV_DESC || cp $ORIG_DESC $ORIG_YUV_DESC || { echo "$ORIG_DESC missing. You need a description file for a YUV"; exit 1; }
54
    . $ORIG_YUV_DESC
55
    [[ $VIDEO_XSIZE != "" && $VIDEO_YSIZE != "" && $VIDEO_FPS != "" ]] || { echo "$ORIG_YUV_DESC not valid. You need a description file for a YUV"; exit 1; }
56

    
57
  else
58
    #$FFMPEG -i $ORIG -s ${VIDEO_XSIZE}x${VIDEO_YSIZE} -r $VIDEO_FPS $ORIG_YUV >${PSNR_TMPPREFIX}ffmpeg.log
59
    $FFMPEG -y -i $ORIG $ORIG_YUV >${PSNR_TMPPREFIX}ffmpeg.log 2>&1
60

    
61
    # Stream #0.0: Video: h264, yuv420p, 352x288, 25 tbr, 1200k tbn, 50 tbc
62
    TMP=`grep "Stream.*Video:" ${PSNR_TMPPREFIX}ffmpeg.log`
63
#    if [[ $TMP =~ Stream.*Video:.*\ ([0-9]+)x([0-9]+),\ ([0-9]+)\ tbr ]]; then #working on GNU bash, version 3.2.48(1)-release (x86_64-pc-linux-gnu)
64
    if [[ $TMP =~ Stream.*Video:.*\ \([0-9]+\)x\([0-9]+\),\ \([0-9]+\)\ tbr ]]; then #working on GNU bash, version 3.1.17(1)-release (x86_64-pc-linux-gnu), also on version 3.2.48(1)-release (x86_64-pc-linux-gnu)
65
      VIDEO_XSIZE=${BASH_REMATCH[1]}
66
      VIDEO_YSIZE=${BASH_REMATCH[2]}
67
      VIDEO_FPS=${BASH_REMATCH[3]}
68
      echo "VIDEO_XSIZE=$VIDEO_XSIZE"  >$ORIG_YUV_DESC
69
      echo "VIDEO_YSIZE=$VIDEO_YSIZE" >>$ORIG_YUV_DESC
70
      echo "VIDEO_FPS=$VIDEO_FPS" >>$ORIG_YUV_DESC
71
    else
72
      echo "Can't get video description (XSIZE, YSIZE or FPS). You need to create a description file by hand"
73
      exit 1
74
    fi
75
  fi
76

    
77
  #$FFMPEG -s ${VIDEO_XSIZE}x${VIDEO_YSIZE} -r 25 -i $ORIG_YUV -f m4v -mbd 2 -b 400k $ORIG_MP4 >>${PSNR_TMPPREFIX}ffmpeg.log
78
  $FFMPEG -y -s ${VIDEO_XSIZE}x${VIDEO_YSIZE} -r $VIDEO_FPS -i $ORIG_YUV $CODER $ORIG_MP4 >>${PSNR_TMPPREFIX}ffmpeg.log
79
  $ANALYSER $ORIG_MP4 > ${PSNR_TMPPREFIX}orig_log.txt
80
}
81

    
82
function chunk {
83
  [[ $# -eq 2 ]] || usage 1
84
  CHUNK_MODE=$1
85
  CHUNK_SIZE=$2
86
  $CHUNKER $ORIG_MP4 $CHUNK_MODE $CHUNK_SIZE  > ${PSNR_TMPPREFIX}chunks.txt
87
}
88

    
89
function calc {
90
  [[ $# -eq 3 ]] || usage 1
91

    
92
  CHUNK_MODE=$1
93
  CHUNK_SIZE=$2
94
  LOST_FILE=$3
95

    
96
  . $ORIG_YUV_DESC
97

    
98
  #cut lost chunks
99
  rm $RECEIVED_MP4 # FIXME: I have no idea why this was needed, but sometimes cutter wasn't overwriting
100
  if [[ $CHUNK_MODE -eq 1 || $CHUNK_MODE -eq 2 || $CHUNK_MODE -eq 3 || $CHUNK_MODE -eq 4  ]]; then
101
    $LOSTFRAMES ${PSNR_TMPPREFIX}chunks.txt $LOST_FILE > ${PSNR_TMPPREFIX}lostframes.txt
102
    echo "running: $CUTTER $ORIG_MP4 $RECEIVED_MP4 ${PSNR_TMPPREFIX}lostframes.txt -2"
103
    $CUTTER $ORIG_MP4 $RECEIVED_MP4 ${PSNR_TMPPREFIX}lostframes.txt -2 2> ${PSNR_TMPPREFIX}cutter_log.txt #TODO: we use -2 as chunk size, which instructs chunker to go frame based
104
  else
105
    echo "running: $CUTTER $ORIG_MP4 $RECEIVED_MP4 $LOST_FILE $CHUNK_SIZE"
106
    $CUTTER $ORIG_MP4 $RECEIVED_MP4 $LOST_FILE $CHUNK_SIZE 2> ${PSNR_TMPPREFIX}cutter_log.txt
107
  fi
108

    
109
  #get chunk count and avgsize
110
  BYTES=`awk '/^bytes:/ {print $2}' ${PSNR_TMPPREFIX}cutter_log.txt`
111
  CHUNKS=`awk '/^chunks:/ {print $2}' ${PSNR_TMPPREFIX}cutter_log.txt`
112
  CHUNKSLOST=`awk '/^chunkslost:/ {print $2}' ${PSNR_TMPPREFIX}cutter_log.txt`
113
  #CHUNK_SIZE_AVG=`(echo - | awk '{ print $BYTES/$CHUNKS}')`
114

    
115
  #analyse losses
116
  $ANALYSER $RECEIVED_MP4 > ${PSNR_TMPPREFIX}received_log.txt
117

    
118
  #reconstruct sequence by duplicating 
119
  $LOGPARSER ${PSNR_TMPPREFIX}orig_log.txt ${PSNR_TMPPREFIX}received_log.txt > ${PSNR_TMPPREFIX}received_dup.txt
120
  $REFILLER $RECEIVED_MP4 $REFILLED_YUV ${PSNR_TMPPREFIX}received_dup.txt > ${PSNR_TMPPREFIX}refiller_log.txt
121
  $EVALPSNR $VIDEO_XSIZE $VIDEO_YSIZE 420 $ORIG_YUV $REFILLED_YUV >${PSNR_TMPPREFIX}psnr_log.txt 2>${PSNR_TMPPREFIX}psnravg_log.txt
122

    
123
  PSNR=`awk '/^psnr:/ {print $8}' ${PSNR_TMPPREFIX}psnravg_log.txt`
124

    
125
  $EVALPSNR $VIDEO_XSIZE $VIDEO_YSIZE 420 $ORIG_YUV $REFILLED_YUV ssim >${PSNR_TMPPREFIX}ssim_log.txt 2>${PSNR_TMPPREFIX}ssimavg_log.txt
126

    
127
  SSIM=`awk '/^ssim:/ {print $8}' ${PSNR_TMPPREFIX}ssimavg_log.txt`
128

    
129
  echo "bytes: $BYTES"
130
  echo "chunks: $CHUNKS"
131
  echo "chunkslost: $CHUNKSLOST"
132
  echo "frames: $FRAMES"
133
  echo "frameslost: $FRAMESLOST"
134
  echo "psnr: $PSNR"
135
  echo "ssim: $SSIM"
136
}
137

    
138
function play {
139
  [[ $# -eq 3 ]] || usage 1
140
  [[ $FFPLAY ]] || { echo "\$FFPLAY not defined"; exit 1; }
141

    
142
  #run all the calculations
143
  calc "$@"
144

    
145
  #play the resulting video
146
  #$FFPLAY -s ${VIDEO_XSIZE}x${VIDEO_YSIZE} -r $VIDEO_FPS -i $ORIG_YUV
147
  $FFPLAY -s ${VIDEO_XSIZE}x${VIDEO_YSIZE} $REFILLED_YUV
148
}
149

    
150
[[ $# -ge 1 ]] || usage 1
151
CMD=$1;
152
shift
153

    
154
case $CMD in
155
  init)
156
    init "$@"
157
    ;;
158
  chunk)
159
    chunk "$@"
160
    ;;
161
  calc)
162
    calc "$@"
163
    ;;
164
  play)
165
    play "$@"
166
    ;;
167
  *)
168
    usage 1
169
    ;;
170
esac