Reland "Remove deprecated barcode scanning functionality"

This is a reland of ff292f30d9

I'm leaving empty .py files in place in order to not break downstream client builds.

Original change's description:
> Remove deprecated barcode scanning functionality
>
> This code is not used anymore, but it's not possible to land this CL
> until issue webrtc:9665 is fixed.
>
> Bug: webrtc:9642,webrtc:9665
> Change-Id: Idb68e9bdf51b4239788cd6869dcb44dae87d7c56
> Reviewed-on: https://webrtc-review.googlesource.com/c/95951
> Reviewed-by: Paulina Hensman <phensman@webrtc.org>
> Reviewed-by: Patrik Höglund <phoglund@webrtc.org>
> Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#25289}

TBR=phensman@webrtc.org,phoglund@webrtc.org

Bug: webrtc:9642, webrtc:9665
Change-Id: I248f8656b14c89b0b92e777f4408ee6a6dad41f9
Reviewed-on: https://webrtc-review.googlesource.com/c/107360
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25296}
This commit is contained in:
Magnus Jedvert 2018-10-22 22:19:20 +02:00 committed by Commit Bot
parent 39feabe35c
commit 165148d84d
14 changed files with 6 additions and 1077 deletions

View file

@ -166,15 +166,12 @@ if (is_android) {
"../build/android/adb_reverse_forwarder.py",
"../examples/androidtests/video_quality_loopback_test.py",
"../resources/reference_video_640x360_30fps.y4m",
"../rtc_tools/barcode_tools/barcode_decoder.py",
"../rtc_tools/barcode_tools/helper_functions.py",
"../rtc_tools/compare_videos.py",
"../rtc_tools/testing/prebuilt_apprtc.zip",
"../rtc_tools/testing/golang/linux/go.tar.gz",
"../rtc_tools/testing/build_apprtc.py",
"../rtc_tools/testing/utils.py",
"../tools_webrtc/video_quality_toolchain/linux/ffmpeg",
"../tools_webrtc/video_quality_toolchain/linux/zxing",
"${root_out_dir}/frame_analyzer_host",
]
}

View file

@ -190,20 +190,13 @@ def RunTest(android_device, adb_path, build_dir, temp_dir, num_retries,
# Run comparison script.
compare_script = os.path.join(SRC_DIR, 'rtc_tools', 'compare_videos.py')
frame_analyzer = os.path.join(build_dir, 'frame_analyzer_host')
zxing_path = os.path.join(TOOLCHAIN_DIR, 'zxing')
stats_file_ref = os.path.join(temp_dir, 'stats_ref.txt')
stats_file_test = os.path.join(temp_dir, 'stats_test.txt')
args = [
'--ref_video', reference_video_yuv,
'--test_video', test_video_yuv,
'--yuv_frame_width', '640',
'--yuv_frame_height', '360',
'--stats_file_ref', stats_file_ref,
'--stats_file_test', stats_file_test,
'--frame_analyzer', frame_analyzer,
'--ffmpeg_path', ffmpeg_path,
'--zxing_path', zxing_path,
]
if chartjson_result_file:
args.extend(['--chartjson_result_file', chartjson_result_file])

View file

@ -1,13 +0,0 @@
# This is trimmed down version of the main tools DEPS file which is to be used
# in Chromiums PyAuto WebRTC video quality measurement test. We will only
# need the Zxing dependencies as we only use the barcode tools in this test.
deps = {
# Used by barcode_tools
"barcode_tools/third_party/zxing/core":
"http://zxing.googlecode.com/svn/trunk/core@2349",
# Used by barcode_tools
"barcode_tools/third_party/zxing/javase":
"http://zxing.googlecode.com/svn/trunk/javase@2349",
}

View file

@ -1,34 +0,0 @@
This file explains how to get the dependencies needed for the barcode tools.
barcode_encoder.py
==================
This script depends on:
* Zxing (Java version)
* Ant (must be installed manually)
* Java
To automatically download Zxing for the encoder script, checkout this directory
as a separate gclient solution, like this:
gclient config http://webrtc.googlecode.com/svn/trunk/webrtc/rtc_tools/barcode_tools
gclient sync
Then the Zxing Java source code will be put in third_party/zxing.
In order to run barcode_encoder.py you then need to build:
* zxing/core/core.jar
* zxing/javase/javase.jar
These are compiled using Ant by running build_zxing.py:
python build_zxing.py
For more info about Zxing, see https://code.google.com/p/zxing/
barcode_decoder.py
==================
This script depends on:
* Zxing (C++ version). You need to checkout from Subversion and build the libs
and zxing SCons targets. SVN URL: http://zxing.googlecode.com/svn/trunk/cpp
* FFMPEG fmpeg 0.11.1
These dependencies must be precompiled separately before running the script.
Make sure to add FFMPEG to the PATH environment variable and provide the path
to the zxing executable using the mandatory command line flag to the script.

295
rtc_tools/barcode_tools/barcode_decoder.py Executable file → Normal file
View file

@ -1,295 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import optparse
import os
import sys
if __name__ == '__main__':
# Make sure we always can import helper_functions.
sys.path.append(os.path.dirname(__file__))
import helper_functions
# Chrome browsertests will throw away stderr; avoid that output gets lost.
sys.stderr = sys.stdout
def ConvertYuvToPngFiles(yuv_file_name, yuv_frame_width, yuv_frame_height,
output_directory, ffmpeg_path):
"""Converts a YUV video file into PNG frames.
The function uses ffmpeg to convert the YUV file. The output of ffmpeg is in
the form frame_xxxx.png, where xxxx is the frame number, starting from 0001.
Args:
yuv_file_name(string): The name of the YUV file.
yuv_frame_width(int): The width of one YUV frame.
yuv_frame_height(int): The height of one YUV frame.
output_directory(string): The output directory where the PNG frames will be
stored.
ffmpeg_path(string): The path to the ffmpeg executable. If None, the PATH
will be searched for it.
Return:
(bool): True if the conversion was OK.
"""
size_string = str(yuv_frame_width) + 'x' + str(yuv_frame_height)
output_files_pattern = os.path.join(output_directory, 'frame_%04d.png')
if not ffmpeg_path:
ffmpeg_path = 'ffmpeg.exe' if sys.platform == 'win32' else 'ffmpeg'
if yuv_file_name.endswith('.yuv'):
command = [ffmpeg_path, '-s', '%s' % size_string, '-i', '%s'
% yuv_file_name, '-f', 'image2', '-vcodec', 'png',
'%s' % output_files_pattern]
else:
command = [ffmpeg_path, '-i', '%s' % yuv_file_name, '-f', 'image2',
'-vcodec', 'png', '%s' % output_files_pattern]
try:
print 'Converting YUV file to PNG images (may take a while)...'
print ' '.join(command)
helper_functions.RunShellCommand(
command, fail_msg='Error during YUV to PNG conversion')
except helper_functions.HelperError, err:
print 'Error executing command: %s. Error: %s' % (command, err)
return False
except OSError:
print 'Did not find %s. Have you installed it?' % ffmpeg_path
return False
return True
def DecodeFrames(input_directory, zxing_path):
"""Decodes the barcodes overlaid in each frame.
The function uses the Zxing command-line tool from the Zxing C++ distribution
to decode the barcode in every PNG frame from the input directory. The frames
should be named frame_xxxx.png, where xxxx is the frame number. The frame
numbers should be consecutive and should start from 0001.
The decoding results in a frame_xxxx.txt file for every successfully decoded
barcode. This file contains the decoded barcode as 12-digit string (UPC-A
format: 11 digits content + one check digit).
Args:
input_directory(string): The input directory from where the PNG frames are
read.
zxing_path(string): The path to the zxing binary. If specified as None,
the PATH will be searched for it.
Return:
(bool): True if the decoding succeeded.
"""
if not zxing_path:
zxing_path = 'zxing.exe' if sys.platform == 'win32' else 'zxing'
print 'Decoding barcodes from PNG files with %s...' % zxing_path
return helper_functions.PerformActionOnAllFiles(
directory=input_directory, file_pattern='frame_',
file_extension='png', start_number=1, action=_DecodeBarcodeInFile,
command_line_decoder=zxing_path)
def _DecodeBarcodeInFile(file_name, command_line_decoder):
"""Decodes the barcode in the upper left corner of a PNG file.
Args:
file_name(string): File name of the PNG file.
command_line_decoder(string): The ZXing command-line decoding tool.
Return:
(bool): True upon success, False otherwise.
"""
command = [command_line_decoder, '--try-harder', '--dump-raw', file_name]
try:
out = helper_functions.RunShellCommand(
command, fail_msg='Error during decoding of %s' % file_name)
text_file = open('%s.txt' % file_name[:-4], 'w')
text_file.write(out)
text_file.close()
except helper_functions.HelperError, err:
print 'Barcode in %s cannot be decoded.' % file_name
print err
return False
except OSError:
print 'Did not find %s. Have you installed it?' % command_line_decoder
return False
return True
def _GenerateStatsFile(stats_file_name, input_directory='.'):
"""Generate statistics file.
The function generates a statistics file. The contents of the file are in the
format <frame_name> <barcode>, where frame name is the name of every frame
(effectively the frame number) and barcode is the decoded barcode. The frames
and the helper .txt files are removed after they have been used.
"""
file_prefix = os.path.join(input_directory, 'frame_')
stats_file = open(stats_file_name, 'w')
print 'Generating stats file: %s' % stats_file_name
for i in range(1, _CountFramesIn(input_directory=input_directory) + 1):
frame_number = helper_functions.ZeroPad(i)
barcode_file_name = file_prefix + frame_number + '.txt'
png_frame = file_prefix + frame_number + '.png'
entry_frame_number = helper_functions.ZeroPad(i-1)
entry = 'frame_' + entry_frame_number + ' '
if os.path.isfile(barcode_file_name):
barcode = _ReadBarcodeFromTextFile(barcode_file_name)
os.remove(barcode_file_name)
if _CheckBarcode(barcode):
entry += (helper_functions.ZeroPad(int(barcode[0:11])) + '\n')
else:
entry += 'Barcode error\n' # Barcode is wrongly detected.
else: # Barcode file doesn't exist.
entry += 'Barcode error\n'
stats_file.write(entry)
os.remove(png_frame)
stats_file.close()
def _ReadBarcodeFromTextFile(barcode_file_name):
"""Reads the decoded barcode for a .txt file.
Args:
barcode_file_name(string): The name of the .txt file.
Return:
(string): The decoded barcode.
"""
barcode_file = open(barcode_file_name, 'r')
barcode = barcode_file.read()
barcode_file.close()
return barcode
def _CheckBarcode(barcode):
"""Check weather the UPC-A barcode was decoded correctly.
This function calculates the check digit of the provided barcode and compares
it to the check digit that was decoded.
Args:
barcode(string): The barcode (12-digit).
Return:
(bool): True if the barcode was decoded correctly.
"""
if len(barcode) != 12:
return False
r1 = range(0, 11, 2) # Odd digits
r2 = range(1, 10, 2) # Even digits except last
dsum = 0
# Sum all the even digits
for i in r1:
dsum += int(barcode[i])
# Multiply the sum by 3
dsum *= 3
# Add all the even digits except the check digit (12th digit)
for i in r2:
dsum += int(barcode[i])
# Get the modulo 10
dsum = dsum % 10
# If not 0 substract from 10
if dsum != 0:
dsum = 10 - dsum
# Compare result and check digit
return dsum == int(barcode[11])
def _CountFramesIn(input_directory='.'):
"""Calculates the number of frames in the input directory.
The function calculates the number of frames in the input directory. The
frames should be named frame_xxxx.png, where xxxx is the number of the frame.
The numbers should start from 1 and should be consecutive.
Args:
input_directory(string): The input directory.
Return:
(int): The number of frames.
"""
file_prefix = os.path.join(input_directory, 'frame_')
file_exists = True
num = 1
while file_exists:
file_name = (file_prefix + helper_functions.ZeroPad(num) + '.png')
if os.path.isfile(file_name):
num += 1
else:
file_exists = False
return num - 1
def _ParseArgs():
"""Registers the command-line options."""
usage = "usage: %prog [options]"
parser = optparse.OptionParser(usage=usage)
parser.add_option('--zxing_path', type='string',
help=('The path to where the zxing executable is located. '
'If omitted, it will be assumed to be present in the '
'PATH with the name zxing[.exe].'))
parser.add_option('--ffmpeg_path', type='string',
help=('The path to where the ffmpeg executable is located. '
'If omitted, it will be assumed to be present in the '
'PATH with the name ffmpeg[.exe].'))
parser.add_option('--yuv_frame_width', type='int', default=640,
help='Width of the YUV file\'s frames. Default: %default')
parser.add_option('--yuv_frame_height', type='int', default=480,
help='Height of the YUV file\'s frames. Default: %default')
parser.add_option('--yuv_file', type='string', default='output.yuv',
help='The YUV file to be decoded. Default: %default')
parser.add_option('--stats_file', type='string', default='stats.txt',
help='The output stats file. Default: %default')
parser.add_option('--png_working_dir', type='string', default='.',
help=('The directory for temporary PNG images to be stored '
'in when decoding from YUV before they\'re barcode '
'decoded. If using Windows and a Cygwin-compiled '
'zxing.exe, you should keep the default value to '
'avoid problems. Default: %default'))
options, _ = parser.parse_args()
return options
def main():
"""The main function.
A simple invocation is:
./webrtc/rtc_tools/barcode_tools/barcode_decoder.py
--yuv_file=<path_and_name_of_overlaid_yuv_video>
--yuv_frame_width=640 --yuv_frame_height=480
--stats_file=<path_and_name_to_stats_file>
"""
options = _ParseArgs()
# Convert the overlaid YUV video into a set of PNG frames.
if not ConvertYuvToPngFiles(options.yuv_file, options.yuv_frame_width,
options.yuv_frame_height,
output_directory=options.png_working_dir,
ffmpeg_path=options.ffmpeg_path):
print 'An error occurred converting from YUV to PNG frames.'
return -1
# Decode the barcodes from the PNG frames.
if not DecodeFrames(input_directory=options.png_working_dir,
zxing_path=options.zxing_path):
print 'An error occurred decoding barcodes from PNG frames.'
return -2
# Generate statistics file.
_GenerateStatsFile(options.stats_file,
input_directory=options.png_working_dir)
print 'Completed barcode decoding.'
return 0
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,372 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import optparse
import os
import sys
import helper_functions
_DEFAULT_BARCODE_WIDTH = 352
_DEFAULT_BARCODES_FILE = 'barcodes.yuv'
def GenerateUpcaBarcodes(number_of_barcodes, barcode_width, barcode_height,
output_directory='.',
path_to_zxing='zxing-read-only'):
"""Generates UPC-A barcodes.
This function generates a number_of_barcodes UPC-A barcodes. The function
calls an example Java encoder from the Zxing library. The barcodes are
generated as PNG images. The width of the barcodes shouldn't be less than 102
pixels because otherwise Zxing can't properly generate the barcodes.
Args:
number_of_barcodes(int): The number of barcodes to generate.
barcode_width(int): Width of barcode in pixels.
barcode_height(int): Height of barcode in pixels.
output_directory(string): Output directory where to store generated
barcodes.
path_to_zxing(string): The path to Zxing.
Return:
(bool): True if the conversion is successful.
"""
base_file_name = os.path.join(output_directory, "barcode_")
jars = _FormJarsString(path_to_zxing)
command_line_encoder = 'com.google.zxing.client.j2se.CommandLineEncoder'
barcode_width = str(barcode_width)
barcode_height = str(barcode_height)
errors = False
for i in range(number_of_barcodes):
suffix = helper_functions.ZeroPad(i)
# Barcodes starting from 0
content = helper_functions.ZeroPad(i, 11)
output_file_name = base_file_name + suffix + ".png"
command = ["java", "-cp", jars, command_line_encoder,
"--barcode_format=UPC_A", "--height=%s" % barcode_height,
"--width=%s" % barcode_width,
"--output=%s" % (output_file_name), "%s" % (content)]
try:
helper_functions.RunShellCommand(
command, fail_msg=('Error during barcode %s generation' % content))
except helper_functions.HelperError as err:
print >> sys.stderr, err
errors = True
return not errors
def ConvertPngToYuvBarcodes(input_directory='.', output_directory='.'):
"""Converts PNG barcodes to YUV barcode images.
This function reads all the PNG files from the input directory which are in
the format frame_xxxx.png, where xxxx is the number of the frame, starting
from 0000. The frames should be consecutive numbers. The output YUV file is
named frame_xxxx.yuv. The function uses ffmpeg to do the conversion.
Args:
input_directory(string): The input direcotry to read the PNG barcodes from.
output_directory(string): The putput directory to write the YUV files to.
Return:
(bool): True if the conversion was without errors.
"""
return helper_functions.PerformActionOnAllFiles(
input_directory, 'barcode_', 'png', 0, _ConvertToYuvAndDelete,
output_directory=output_directory, pattern='barcode_')
def _ConvertToYuvAndDelete(output_directory, file_name, pattern):
"""Converts a PNG file to a YUV file and deletes the PNG file.
Args:
output_directory(string): The output directory for the YUV file.
file_name(string): The PNG file name.
pattern(string): The file pattern of the PNG/YUV file. The PNG/YUV files are
named patternxx..x.png/yuv, where xx..x are digits starting from 00..0.
Return:
(bool): True upon successful conversion, false otherwise.
"""
# Pattern should be in file name
if not pattern in file_name:
return False
pattern_position = file_name.rfind(pattern)
# Strip the path to the PNG file and replace the png extension with yuv
yuv_file_name = file_name[pattern_position:-3] + 'yuv'
yuv_file_name = os.path.join(output_directory, yuv_file_name)
command = ['ffmpeg', '-i', '%s' % (file_name), '-pix_fmt', 'yuv420p',
'%s' % (yuv_file_name)]
try:
helper_functions.RunShellCommand(
command, fail_msg=('Error during PNG to YUV conversion of %s' %
file_name))
os.remove(file_name)
except helper_functions.HelperError as err:
print >> sys.stderr, err
return False
return True
def CombineYuvFramesIntoOneFile(output_file_name, input_directory='.'):
"""Combines several YUV frames into one YUV video file.
The function combines the YUV frames from input_directory into one YUV video
file. The frames should be named in the format frame_xxxx.yuv where xxxx
stands for the frame number. The numbers have to be consecutive and start from
0000. The YUV frames are removed after they have been added to the video.
Args:
output_file_name(string): The name of the file to produce.
input_directory(string): The directory from which the YUV frames are read.
Return:
(bool): True if the frame stitching went OK.
"""
output_file = open(output_file_name, "wb")
success = helper_functions.PerformActionOnAllFiles(
input_directory, 'barcode_', 'yuv', 0, _AddToFileAndDelete,
output_file=output_file)
output_file.close()
return success
def _AddToFileAndDelete(output_file, file_name):
"""Adds the contents of a file to a previously opened file.
Args:
output_file(file): The ouput file, previously opened.
file_name(string): The file name of the file to add to the output file.
Return:
(bool): True if successful, False otherwise.
"""
input_file = open(file_name, "rb")
input_file_contents = input_file.read()
output_file.write(input_file_contents)
input_file.close()
try:
os.remove(file_name)
except OSError as e:
print >> sys.stderr, 'Error deleting file %s.\nError: %s' % (file_name, e)
return False
return True
def _OverlayBarcodeAndBaseFrames(barcodes_file, base_file, output_file,
barcodes_component_sizes,
base_component_sizes):
"""Overlays the next YUV frame from a file with a barcode.
Args:
barcodes_file(FileObject): The YUV file containing the barcodes (opened).
base_file(FileObject): The base YUV file (opened).
output_file(FileObject): The output overlaid file (opened).
barcodes_component_sizes(list of tuples): The width and height of each Y, U
and V plane of the barcodes YUV file.
base_component_sizes(list of tuples): The width and height of each Y, U and
V plane of the base YUV file.
Return:
(bool): True if there are more planes (i.e. frames) in the base file, false
otherwise.
"""
# We will loop three times - once for the Y, U and V planes
for ((barcode_comp_width, barcode_comp_height),
(base_comp_width, base_comp_height)) in zip(barcodes_component_sizes,
base_component_sizes):
for base_row in range(base_comp_height):
barcode_plane_traversed = False
if (base_row < barcode_comp_height) and not barcode_plane_traversed:
barcode_plane = barcodes_file.read(barcode_comp_width)
if barcode_plane == "":
barcode_plane_traversed = True
else:
barcode_plane_traversed = True
base_plane = base_file.read(base_comp_width)
if base_plane == "":
return False
if not barcode_plane_traversed:
# Substitute part of the base component with the top component
output_file.write(barcode_plane)
base_plane = base_plane[barcode_comp_width:]
output_file.write(base_plane)
return True
def OverlayYuvFiles(barcode_width, barcode_height, base_width, base_height,
barcodes_file_name, base_file_name, output_file_name):
"""Overlays two YUV files starting from the upper left corner of both.
Args:
barcode_width(int): The width of the barcode (to be overlaid).
barcode_height(int): The height of the barcode (to be overlaid).
base_width(int): The width of a frame of the base file.
base_height(int): The height of a frame of the base file.
barcodes_file_name(string): The name of the YUV file containing the YUV
barcodes.
base_file_name(string): The name of the base YUV file.
output_file_name(string): The name of the output file where the overlaid
video will be written.
"""
# Component sizes = [Y_sizes, U_sizes, V_sizes]
barcodes_component_sizes = [(barcode_width, barcode_height),
(barcode_width/2, barcode_height/2),
(barcode_width/2, barcode_height/2)]
base_component_sizes = [(base_width, base_height),
(base_width/2, base_height/2),
(base_width/2, base_height/2)]
barcodes_file = open(barcodes_file_name, 'rb')
base_file = open(base_file_name, 'rb')
output_file = open(output_file_name, 'wb')
data_left = True
while data_left:
data_left = _OverlayBarcodeAndBaseFrames(barcodes_file, base_file,
output_file,
barcodes_component_sizes,
base_component_sizes)
barcodes_file.close()
base_file.close()
output_file.close()
def CalculateFramesNumberFromYuv(yuv_width, yuv_height, file_name):
"""Calculates the number of frames of a YUV video.
Args:
yuv_width(int): Width of a frame of the yuv file.
yuv_height(int): Height of a frame of the YUV file.
file_name(string): The name of the YUV file.
Return:
(int): The number of frames in the YUV file.
"""
file_size = os.path.getsize(file_name)
y_plane_size = yuv_width * yuv_height
u_plane_size = (yuv_width/2) * (yuv_height/2) # Equals to V plane size too
frame_size = y_plane_size + (2 * u_plane_size)
return int(file_size/frame_size) # Should be int anyway
def _FormJarsString(path_to_zxing):
"""Forms the the Zxing core and javase jars argument.
Args:
path_to_zxing(string): The path to the Zxing checkout folder.
Return:
(string): The newly formed jars argument.
"""
javase_jar = os.path.join(path_to_zxing, "javase", "javase.jar")
core_jar = os.path.join(path_to_zxing, "core", "core.jar")
delimiter = ':'
if os.name != 'posix':
delimiter = ';'
return javase_jar + delimiter + core_jar
def _ParseArgs():
"""Registers the command-line options."""
usage = "usage: %prog [options]"
parser = optparse.OptionParser(usage=usage)
parser.add_option('--barcode_width', type='int',
default=_DEFAULT_BARCODE_WIDTH,
help=('Width of the barcodes to be overlaid on top of the'
' base file. Default: %default'))
parser.add_option('--barcode_height', type='int', default=32,
help=('Height of the barcodes to be overlaid on top of the'
' base file. Default: %default'))
parser.add_option('--base_frame_width', type='int', default=352,
help=('Width of the base YUV file\'s frames. '
'Default: %default'))
parser.add_option('--base_frame_height', type='int', default=288,
help=('Height of the top YUV file\'s frames. '
'Default: %default'))
parser.add_option('--barcodes_yuv', type='string',
default=_DEFAULT_BARCODES_FILE,
help=('The YUV file with the barcodes in YUV. '
'Default: %default'))
parser.add_option('--base_yuv', type='string', default='base.yuv',
help=('The base YUV file to be overlaid. '
'Default: %default'))
parser.add_option('--output_yuv', type='string', default='output.yuv',
help=('The output YUV file containing the base overlaid'
' with the barcodes. Default: %default'))
parser.add_option('--png_barcodes_output_dir', type='string', default='.',
help=('Output directory where the PNG barcodes will be '
'generated. Default: %default'))
parser.add_option('--png_barcodes_input_dir', type='string', default='.',
help=('Input directory from where the PNG barcodes will be '
'read. Default: %default'))
parser.add_option('--yuv_barcodes_output_dir', type='string', default='.',
help=('Output directory where the YUV barcodes will be '
'generated. Default: %default'))
parser.add_option('--yuv_frames_input_dir', type='string', default='.',
help=('Input directory from where the YUV will be '
'read before combination. Default: %default'))
parser.add_option('--zxing_dir', type='string', default='zxing',
help=('Path to the Zxing barcodes library. '
'Default: %default'))
options = parser.parse_args()[0]
return options
def main():
"""The main function.
A simple invocation will be:
./webrtc/rtc_tools/barcode_tools/barcode_encoder.py --barcode_height=32
--base_frame_width=352 --base_frame_height=288
--base_yuv=<path_and_name_of_base_file>
--output_yuv=<path and name_of_output_file>
"""
options = _ParseArgs()
# The barcodes with will be different than the base frame width only if
# explicitly specified at the command line.
if options.barcode_width == _DEFAULT_BARCODE_WIDTH:
options.barcode_width = options.base_frame_width
# If the user provides a value for the barcodes YUV video file, we will keep
# it. Otherwise we create a temp file which is removed after it has been used.
keep_barcodes_yuv_file = False
if options.barcodes_yuv != _DEFAULT_BARCODES_FILE:
keep_barcodes_yuv_file = True
# Calculate the number of barcodes - it is equal to the number of frames in
# the base file.
number_of_barcodes = CalculateFramesNumberFromYuv(
options.base_frame_width, options.base_frame_height, options.base_yuv)
script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
zxing_dir = os.path.join(script_dir, 'third_party', 'zxing')
# Generate barcodes - will generate them in PNG.
GenerateUpcaBarcodes(number_of_barcodes, options.barcode_width,
options.barcode_height,
output_directory=options.png_barcodes_output_dir,
path_to_zxing=zxing_dir)
# Convert the PNG barcodes to to YUV format.
ConvertPngToYuvBarcodes(options.png_barcodes_input_dir,
options.yuv_barcodes_output_dir)
# Combine the YUV barcodes into one YUV file.
CombineYuvFramesIntoOneFile(options.barcodes_yuv,
input_directory=options.yuv_frames_input_dir)
# Overlay the barcodes over the base file.
OverlayYuvFiles(options.barcode_width, options.barcode_height,
options.base_frame_width, options.base_frame_height,
options.barcodes_yuv, options.base_yuv, options.output_yuv)
if not keep_barcodes_yuv_file:
# Remove the temporary barcodes YUV file
os.remove(options.barcodes_yuv)
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,44 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import os
import subprocess
import sys
def RunAntBuildCommand(path_to_ant_build_file):
"""Tries to build the passed build file with ant."""
ant_executable = 'ant'
if sys.platform == 'win32':
if os.getenv('ANT_HOME'):
ant_executable = os.path.join(os.getenv('ANT_HOME'), 'bin', 'ant.bat')
else:
ant_executable = 'ant.bat'
cmd = [ant_executable, '-buildfile', path_to_ant_build_file]
try:
process = subprocess.Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
process.wait()
if process.returncode != 0:
print >> sys.stderr, 'Failed to execute: %s' % ' '.join(cmd)
return process.returncode
except subprocess.CalledProcessError as e:
print >> sys.stderr, 'Failed to execute: %s.\nCause: %s' % (' '.join(cmd),
e)
return -1
def main():
core_build = os.path.join('third_party', 'zxing', 'core', 'build.xml')
RunAntBuildCommand(core_build)
javase_build = os.path.join('third_party', 'zxing', 'javase', 'build.xml')
return RunAntBuildCommand(javase_build)
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,105 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import multiprocessing
import os
import subprocess
import sys
_DEFAULT_PADDING = 4
class HelperError(Exception):
"""Exception raised for errors in the helper."""
pass
def ZeroPad(number, padding=_DEFAULT_PADDING):
"""Converts an int into a zero padded string.
Args:
number(int): The number to convert.
padding(int): The number of chars in the output. Note that if you pass for
example number=23456 and padding=4, the output will still be '23456',
i.e. it will not be cropped. If you pass number=2 and padding=4, the
return value will be '0002'.
Return:
(string): The zero padded number converted to string.
"""
return str(number).zfill(padding)
def RunShellCommand(cmd_list, fail_msg=None):
"""Executes a command.
Args:
cmd_list(list): Command list to execute.
fail_msg(string): Message describing the error in case the command fails.
Return:
(string): The standard output from running the command.
Raise:
HelperError: If command fails.
"""
process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
if process.returncode != 0:
if fail_msg:
print >> sys.stderr, fail_msg
raise HelperError('Failed to run %s: command returned %d and printed '
'%s and %s' % (' '.join(cmd_list), process.returncode,
output, error))
return output.strip()
def PerformActionOnAllFiles(directory, file_pattern, file_extension,
start_number, action, **kwargs):
"""Function that performs a given action on all files matching a pattern.
It is assumed that the files are named file_patternxxxx.file_extension, where
xxxx are digits starting from start_number.
Args:
directory(string): The directory where the files live.
file_pattern(string): The name pattern of the files.
file_extension(string): The files' extension.
start_number(int): From where to start to count frames.
action(function): The action to be performed over the files. Must return
False if the action failed, True otherwise. It should take a file name
as the first argument and **kwargs as arguments. The function must be
possible to pickle, so it cannot be a bound function (for instance).
Return:
(bool): Whether performing the action over all files was successful or not.
"""
file_prefix = os.path.join(directory, file_pattern)
file_number = start_number
process_pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
results = []
while True:
zero_padded_file_number = ZeroPad(file_number)
file_name = file_prefix + zero_padded_file_number + '.' + file_extension
if not os.path.isfile(file_name):
break
future = process_pool.apply_async(action, args=(file_name,), kwds=kwargs)
results.append(future)
file_number += 1
successful = True
for result in results:
if not result.get():
print "At least one action %s failed for files %sxxxx.%s." % (
action, file_pattern, file_extension)
successful = False
process_pool.close()
return successful

View file

@ -1,125 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import optparse
import os
import sys
def _CropOneFrame(yuv_file, output_file, component_sizes):
"""Crops one frame.
This function crops one frame going through all the YUV planes and cropping
respective amount of rows.
Args:
yuv_file(file): The opened (for binary reading) YUV file.
output_file(file): The opened (for binary writing) file.
component_sizes(list of 3 3-ples): The list contains the sizes for all the
planes (Y, U, V) of the YUV file plus the crop_height scaled for every
plane. The sizes equal width, height and crop_height for the Y plane,
and are equal to width/2, height/2 and crop_height/2 for the U and V
planes.
Return:
(bool): True if there are more frames to crop, False otherwise.
"""
for comp_width, comp_height, comp_crop_height in component_sizes:
for row in range(comp_height):
# Read the plane data for this row.
yuv_plane = yuv_file.read(comp_width)
# If the plane is empty, we have reached the end of the file.
if yuv_plane == "":
return False
# Only write the plane data for the rows bigger than crop_height.
if row >= comp_crop_height:
output_file.write(yuv_plane)
return True
def CropFrames(yuv_file_name, output_file_name, width, height, crop_height):
"""Crops rows of pixels from the top of the YUV frames.
This function goes through all the frames in a video and crops the crop_height
top pixel rows of every frame.
Args:
yuv_file_name(string): The name of the YUV file to be cropped.
output_file_name(string): The name of the output file where the result will
be written.
width(int): The width of the original YUV file.
height(int): The height of the original YUV file.
crop_height(int): The height (the number of pixel rows) to be cropped from
the frames.
"""
# Component sizes = [Y_sizes, U_sizes, V_sizes].
component_sizes = [(width, height, crop_height),
(width/2, height/2, crop_height/2),
(width/2, height/2, crop_height/2)]
yuv_file = open(yuv_file_name, 'rb')
output_file = open(output_file_name, 'wb')
data_left = True
while data_left:
data_left = _CropOneFrame(yuv_file, output_file, component_sizes)
yuv_file.close()
output_file.close()
def _ParseArgs():
"""Registers the command-line options."""
usage = "usage: %prog [options]"
parser = optparse.OptionParser(usage=usage)
parser.add_option('--width', type='int',
default=352,
help=('Width of the YUV file\'s frames. '
'Default: %default'))
parser.add_option('--height', type='int', default=288,
help=('Height of the YUV file\'s frames. '
'Default: %default'))
parser.add_option('--crop_height', type='int', default=32,
help=('How much of the top of the YUV file to crop. '
'Has to be module of 2. Default: %default'))
parser.add_option('--yuv_file', type='string',
help=('The YUV file to be cropped.'))
parser.add_option('--output_file', type='string', default='output.yuv',
help=('The output YUV file containing the cropped YUV. '
'Default: %default'))
options = parser.parse_args()[0]
if not options.yuv_file:
parser.error('yuv_file argument missing. Please specify input YUV file!')
return options
def main():
"""A tool to crop rows of pixels from the top part of a YUV file.
A simple invocation will be:
./yuv_cropper.py --width=640 --height=480 --crop_height=32
--yuv_file=<path_and_name_of_yuv_file>
--output_yuv=<path and name_of_output_file>
"""
options = _ParseArgs()
if os.path.getsize(options.yuv_file) == 0:
sys.stderr.write('Error: The YUV file you have passed has size 0. The '
'produced output will also have size 0.\n')
return -1
CropFrames(options.yuv_file, options.output_file, options.width,
options.height, options.crop_height)
return 0
if __name__ == '__main__':
sys.exit(main())

View file

@ -46,25 +46,15 @@ def _ParseArgs():
parser.add_option('--vmaf_phone_model', action='store_true',
help='Whether to use phone model in VMAF.')
parser.add_option('--barcode_decoder', type='string',
help=('Path to the barcode decoder script. By default, we '
'will assume we can find it in barcode_tools/'
'relative to this directory.'))
help=('DEPRECATED'))
parser.add_option('--ffmpeg_path', type='string',
help=('The path to where the ffmpeg executable is located. '
'If omitted, it will be assumed to be present in the '
'PATH with the name ffmpeg[.exe].'))
help=('DEPRECATED'))
parser.add_option('--zxing_path', type='string',
help=('The path to where the zxing executable is located. '
'If omitted, it will be assumed to be present in the '
'PATH with the name zxing[.exe].'))
help=('DEPRECATED'))
parser.add_option('--stats_file_ref', type='string', default='stats_ref.txt',
help=('Path to the temporary stats file to be created and '
'used for the reference video file. '
'Default: %default'))
help=('DEPRECATED'))
parser.add_option('--stats_file_test', type='string',
default='stats_test.txt',
help=('Path to the temporary stats file to be created and '
'used for the test video file. Default: %default'))
help=('DEPRECATED'))
parser.add_option('--stats_file', type='string',
help=('DEPRECATED'))
parser.add_option('--yuv_frame_width', type='int', default=640,
@ -75,11 +65,6 @@ def _ParseArgs():
help='Where to store perf results in chartjson format.')
options, _ = parser.parse_args()
if options.stats_file:
options.stats_file_test = options.stats_file
print ('WARNING: Using deprecated switch --stats_file. '
'The new flag is --stats_file_test.')
if not options.ref_video:
parser.error('You must provide a path to the reference video!')
if not os.path.exists(options.ref_video):
@ -108,34 +93,6 @@ def _DevNull():
"""
return open(os.devnull, 'r')
def DecodeBarcodesInVideo(options, path_to_decoder, video, stat_file):
# Run barcode decoder on the test video to identify frame numbers.
png_working_directory = tempfile.mkdtemp()
cmd = [
sys.executable,
path_to_decoder,
'--yuv_file=%s' % video,
'--yuv_frame_width=%d' % options.yuv_frame_width,
'--yuv_frame_height=%d' % options.yuv_frame_height,
'--stats_file=%s' % stat_file,
'--png_working_dir=%s' % png_working_directory,
]
if options.zxing_path:
cmd.append('--zxing_path=%s' % options.zxing_path)
if options.ffmpeg_path:
cmd.append('--ffmpeg_path=%s' % options.ffmpeg_path)
barcode_decoder = subprocess.Popen(cmd, stdin=_DevNull(),
stdout=sys.stdout, stderr=sys.stderr)
barcode_decoder.wait()
shutil.rmtree(png_working_directory)
if barcode_decoder.returncode != 0:
print 'Failed to run barcode decoder script.'
return 1
return 0
def _RunFrameAnalyzer(options, yuv_directory=None):
"""Run frame analyzer to compare the videos and print output."""
@ -214,27 +171,9 @@ def main():
Running vmaf requires the following arguments:
--vmaf, --vmaf_model, --yuv_frame_width, --yuv_frame_height
Notice that the prerequisites for barcode_decoder.py also applies to this
script. The means the following executables have to be available in the PATH:
* zxing
* ffmpeg
"""
options = _ParseArgs()
if options.barcode_decoder:
path_to_decoder = options.barcode_decoder
else:
path_to_decoder = os.path.join(SCRIPT_DIR, 'barcode_tools',
'barcode_decoder.py')
if DecodeBarcodesInVideo(options, path_to_decoder,
options.ref_video, options.stats_file_ref) != 0:
return 1
if DecodeBarcodesInVideo(options, path_to_decoder,
options.test_video, options.stats_file_test) != 0:
return 1
if options.vmaf:
try:
# Directory to save temporary YUV files for VMAF in frame_analyzer.

View file

@ -79,7 +79,7 @@ def _ParseArgs():
help='Path to the frame analyzer executable.'
'Default: %default')
parser.add_option('--zxing_path', type='string',
help='Path to the zebra xing barcode analyzer.')
help='DEPRECATED.')
parser.add_option('--ref_rec_dir', type='string', default='ref',
help='Path to where reference recordings will be created.'
'Ideally keep the ref and test directories on separate'
@ -118,8 +118,6 @@ def _ParseArgs():
'generated!')
if not os.path.isfile(options.frame_analyzer):
parser.warning('Cannot find frame_analyzer, no metrics will be generated!')
if not os.path.isfile(options.zxing_path):
parser.warning('Cannot find Zebra Xing, no metrics will be generated!')
return options
@ -442,12 +440,6 @@ def CompareVideos(options, cropped_ref_file, cropped_test_file):
'--ref_video=%s' % cropped_ref_file,
'--test_video=%s' % cropped_test_file,
'--frame_analyzer=%s' % os.path.abspath(options.frame_analyzer),
'--zxing_path=%s' % options.zxing_path,
'--ffmpeg_path=%s' % options.ffmpeg,
'--stats_file_ref=%s_stats.txt' %
os.path.join(os.path.dirname(cropped_ref_file), cropped_ref_file),
'--stats_file_test=%s_stats.txt' %
os.path.join(os.path.dirname(cropped_test_file), cropped_test_file),
'--yuv_frame_height=%d' % crop_height,
'--yuv_frame_width=%d' % crop_width
]
@ -472,7 +464,6 @@ def main():
--app_name AppRTCMobile \
--ffmpeg ./ffmpeg --ref_video_device=/dev/video0 \
--test_video_device=/dev/video1 \
--zxing_path ./zxing \
--test_crop_parameters 'crop=950:420:130:56' \
--ref_crop_parameters 'hflip, crop=950:420:130:56' \
--ref_rec_dir /tmp/ref \

View file

@ -1 +0,0 @@
3e2a25eaa2e207a1e569c6585e50addb20bca89a

View file

@ -1 +0,0 @@
6778e3ac489f4fc18a1ed1252bbd6eca54c9960e

View file

@ -1 +0,0 @@
86ca3148778079665ad5b9459311d343a1865943