def cleanup(self):
        """
        Cleans up on exiting the application, i.e. the manipulation settings are reverted to normal settings.
        """
        """
        tc: http://lartc.org/manpages/tc.txt

        qdisc <OPERATOR=add|change|del|replace|link>: defines the operation to be done on the traffic control
        dev <DEVICE>: sets the device to set the traffic control for
        <NODE=root|parent>: node of the device to operate in
        """

        # delete tc settings -> reset to default
        tc_cleanup_command = Command('tc')
        tc_cleanup_command.set_as_argument('QDISC-OPERATION', 'qdisc del') \
                          .set_as_argument('DEVICE', 'dev %s root' % STREAM_NETWORK_INTERFACE)

        self._cmd(tc_cleanup_command)
    def __get_new_tc_add_command():
        """
        Generates and returns a command for the TC tool, which adds a qdisc-operation.

        :return: A TC command which adds a qdisc-operation
        :rtype: Command
        """
        """
        tc: http://lartc.org/manpages/tc.txt

        qdisc <OPERATOR=add|change|del|replace|link>: defines the operation to be done on the traffic control
        dev <DEVICE>: sets the device to set the traffic control for
        <NODE=root|parent>: node of the device to operate in
        """

        tc_command = Command('tc')
        tc_command.set_as_argument('QDISC-OPERATION', 'qdisc add') \
                  .set_as_argument('DEVICE', 'dev %s root' % STREAM_NETWORK_INTERFACE)

        return tc_command
Exemple #3
0
    def __get_base_telchemy_command(self):
        """
        Returns a basic telchemy command, which can be used for further specifications.

        :return: A basic telchemy command, which can be used for further specifications
        :rtype: Command
        """

        telchemy_command = Command(self._parent.MANIPULATOR_PROGRAM_PATH)

        # specify markov model | NOTE: the P.NAMS/P.BNAMS model is not specified in here!
        if self.__is_markov_2_state:
            telchemy_command.set_as_posix_option('m', 2)
        elif self.__is_markov_4_state:
            telchemy_command.set_as_posix_option('m', 4)

        # specify loss insertion start time
        telchemy_command.set_as_posix_option('s', self._settings[TelchemyMarkovRes.DB_FIELD_START_AFTER])

        # specify loss insertion end time
        telchemy_command.set_as_posix_option('e', self._settings[TelchemyMarkovRes.DB_FIELD_END_BEFORE])

        return telchemy_command
Exemple #4
0
    def __get_general_encoding_command_without_destination(self, encoding_set, src_set, is_debug_mode):
        """
        Returns the general encoding command without a destination path. After adding a destination path it
        can be directly executed or further modified (useful for twopass coding)

        :param encoding_set: the configuration set describing the encoding configuration
        :type encoding_set: dict

        :param src_set: the settings of the source to encode
        :type src_set: dict

        :param is_debug_mode: True is debug logging is allowed, False otherwise
        :type is_debug_mode: bool

        :return: the general encoding command without a destination path.
        :rtype: Command
        """

        assert self._src_path != self.DEFAULT_SRC_PATH
        assert self._destination_path != self.DEFAULT_DESTINATION_PATH
        assert isinstance(encoding_set, dict)
        assert isinstance(src_set, dict)

        # build encoder command
        command = Command(APP_PATH)

        if EncodingTable.DB_TABLE_FIELD_NAME_ALTERNATIVE_COMMAND_LINE in encoding_set:
            self.__extend_command_with_alternative_command_line(
                command,
                encoding_set[EncodingTable.DB_TABLE_FIELD_NAME_ALTERNATIVE_COMMAND_LINE],
                src_set,
                is_debug_mode
            )
        else:
            self.__extend_command_with_encoding_table_settings(
                command,
                encoding_set,
                src_set,
                is_debug_mode
            )

        return command
    def __handle_tcpdump_on_destination(self):
        """
        Starts a "tcpdump" process, which captures packets transmitted over the network and collects them in a
        pre-specified destination file.

        :return: The tcpdump process which is used to dump the transmitted packets into the destination file
        :rtype: Process
        """
        """
        tcpdump: http://www.tcpdump.org/tcpdump_man.html

        -i <INPUT>: specifies input resource
        -w <OUTPUT>: specifies output resource to write pcap content

        additional filter used here: '<PROTOCOL> port <PORT>'
        --> Capture only all packets which are delivered via the <PROTOCOL> protocol over port <PORT>
        """

        tcpdump_command = Command('tcpdump')
        tcpdump_command.set_as_subprocess() \
                       .set_as_posix_option('i', STREAM_NETWORK_INTERFACE) \
                       .set_as_posix_option('w', self._dst_file_path) \
                       .set_as_argument('PROTOCOL', STREAM_PROTOCOL_UDP) \
                       .set_as_argument('PORT', 'port %d' % STREAM_PORT)

        # set loggings
        if self._log_folder and self._log_suffix:
            tcpdump_log_file_path = self._get_log_file_path('tcpdump')
            tcpdump_command.set_as_log_file(tcpdump_log_file_path) \
                           .set_std_err_redirect_to_file()

        process = self._cmd(tcpdump_command)

        # wait a short time wherein the process is able to initialize itself
        if not self._is_dry_run:
            from time import sleep
            sleep(1)

        return process
    def __replay_stream(self):
        """
        Replays the pre-specified packet source stream.
        """
        """
        tcpreplay: http://tcpreplay.synfin.net/wiki/tcpreplay

        -i <NETWORK_INTERFACE>: replay packets to the interface <NETWORK_INTERFACE>

        <INPUT>: input resource to replay the packets from
        """

        tcpreplay_command = Command('tcpreplay')
        tcpreplay_command.set_as_posix_option('i', STREAM_NETWORK_INTERFACE) \
                         .set_as_argument('INPUT', self._src_file_path)

        if self._log_folder:
            from os import devnull
            tcpreplay_log_file_path = self._get_log_file_path('tcpreplay')
            tcpreplay_command.set_std_err_redirect_to_std_out() \
                             .tee(tcpreplay_log_file_path + ' > ' + devnull) \

        self._cmd(tcpreplay_command)
Exemple #7
0
    def manipulate(self):
        """
        Performs the manipulation based on existing traces.
        """

        telchemy_command = Command(self._parent.MANIPULATOR_PROGRAM_PATH)
        trace_file_path = self._path \
                     + TRACES_FOLDER_NAME \
                     + PATH_SEPARATOR \
                     + self._settings[TelchemyReadTraceRes.DB_FIELD_NAME_TRACE_FILE_NAME]

        assert isfile(trace_file_path) and exists(trace_file_path), \
            "The specified trace file: `%s` is not a valid existing file!" % trace_file_path

        self._set_telchemy_command_file_input_output_options(telchemy_command)
        telchemy_command.set_as_posix_option('r', trace_file_path)

        # set loggings
        if self._log_folder and self._log_suffix:
            telchemy_log_file_path = self._get_log_file_path('telchemy')
            telchemy_command.set_as_log_file(telchemy_log_file_path)

        self._cmd(telchemy_command)
Exemple #8
0
    def __stream_source_by_hrc_set(self, src_id, hrc_set):
        """
        Streams a source by the given settings of the HRC table
        :param src_id: the id of the source to send the stream
        :param hrc_set: the set which contains all information
        """

        assert isinstance(src_id, int)
        assert isinstance(hrc_set, dict)

        codec = self._get_codec_by_hrc_set(hrc_set)
        file_path = self._path + STREAM_SOURCE_DIR + PATH_SEPARATOR + self._get_output_file_name(
            src_id, hrc_set, codec.get_raw_file_extension()
        )

        if not isfile(file_path):
            raise Warning(
                'Source %d could not be streamed, because no appropriate file has been found' % src_id
            )

        pcap_path = self._path + STREAM_DESTINATION_DIR + PATH_SEPARATOR + self._get_output_file_name(
            src_id, hrc_set, STREAM_OUTPUT_FILE_TYPE_EXTENSION
        )

        # check if the destination path already exists -> check override mode to skip or to override
        assert self._hrc_table.DB_TABLE_FIELD_NAME_HRC_ID in hrc_set
        if exists(pcap_path):
            if self._is_override_mode:
                if not self._is_dry_run:
                    remove(pcap_path)

                    ts_path = self._path + STREAM_SOURCE_DIR + PATH_SEPARATOR + self._get_output_file_name(
                        src_id, hrc_set, 'ts'
                    )

                    # remove also old ts conversion, if one exists!
                    if exists(ts_path):
                        remove(ts_path)

                print "# \033[95m\033[1mREMOVE src %d : hrc %d\033[0m"\
                      % (src_id, int(hrc_set[self._hrc_table.DB_TABLE_FIELD_NAME_HRC_ID]))
            else:
                assert self._hrc_table.DB_TABLE_FIELD_NAME_HRC_ID in hrc_set
                print "# \033[95m\033[1mSKIP src %d : hrc %d\033[0m"\
                      % (src_id, int(hrc_set[self._hrc_table.DB_TABLE_FIELD_NAME_HRC_ID]))
                return

        # setup coder
        coder_id = hrc_set[self._hrc_table.DB_TABLE_FIELD_NAME_CODER_ID]
        coder = get_validated_coder(coder_id, self._config.get_config_folder_path())

        assert self._hrc_table.DB_TABLE_FIELD_NAME_STREAM_MODE in hrc_set
        stream_mode = hrc_set[self._hrc_table.DB_TABLE_FIELD_NAME_STREAM_MODE]

        if stream_mode == self._hrc_table.DB_STREAM_MODE_FIELD_VALUE_MPEGTS_UDP:
            file_path = self.__convert_to_mpeg2ts(file_path, codec.get_library_name())

        coder.set_src_path(file_path)

        if self._log_folder:
            coder_log_file_path = self._log_folder \
                                  + PATH_SEPARATOR \
                                  + coder.__class__.__name__ \
                                  + '_' \
                                  + self._get_output_file_name(src_id, hrc_set, 'log')
            coder.set_log_file(coder_log_file_path)

        #
        # Activate tcp dump to record the streamed packets
        #

        """
        tcpdump: http://www.tcpdump.org/tcpdump_man.html

        -i <INPUT>: specifies input resource
        -w <OUTPUT>: specifies output resource to write pcap content

        additional filter used here: '<PROTOCOL> port <PORT>'
        --> Capture only all packets which are delivered via the <PROTOCOL> protocol over port <PORT>
        """
        tcpdump_command = Command('tcpdump')
        tcpdump_command.set_as_subprocess() \
            .set_as_posix_option('i', STREAM_NETWORK_INTERFACE) \
            .set_as_posix_option('w', pcap_path) \
            .set_as_argument('PROTOCOL', STREAM_PROTOCOL_UDP) \
            .set_as_argument('PORT', 'port %d' % STREAM_PORT)

        # set tcpdump log
        if self._log_folder:
            tcpdump_log_file_path = self._log_folder \
                                    + PATH_SEPARATOR \
                                    + 'tcpdump_' \
                                    + self._get_output_file_name(src_id, hrc_set, 'log')
            tcpdump_command.set_as_log_file(tcpdump_log_file_path) \
                .set_std_err_redirect_to_file()

        tcpdump_process = self._cmd(tcpdump_command)

        if not self._is_dry_run:
            from time import sleep
            sleep(1)

        #
        # Stream video
        #

        coder.set_dry_mode(self._is_dry_run) \
             .send_stream(
                STREAM_SERVER,
                STREAM_PORT,
                stream_mode,
                codec
             )

        #
        # Stop tcpdump
        #

        if isinstance(tcpdump_process, Process):
            self._terminate_process_with_children(tcpdump_process)
Exemple #9
0
    def __convert_to_mpeg2ts(self, input_path, codec_name):
        """
        Converts an input file to a specific output format with MP4Box to MPEG2-TS

        :param input_path: the path to the file to convert
        :type input_path: basestring

        :param codec_name: the name of the codec to use for the conversion
        :type codec_name: basestring

        :return: the path where the converted file can be found after the operation succeeded
        :rtype: basestring
        """

        assert isinstance(input_path, basestring)
        assert isinstance(codec_name, basestring)
        assert isfile(input_path)
        assert exists(input_path)

        """
        ffmpeg: http://ffmpeg.org/
        """
        from coder.ffmpegCoder import APP_PATH as FFMPEG_PATH
        ffmpeg_command = Command(FFMPEG_PATH)

        """
        i: input file
        """
        ffmpeg_command.set_as_posix_option('i', input_path)

        """
        c: codec used
        """
        ffmpeg_command.set_as_posix_option('c:v', codec_name)

        """
        set output file
        """
        output_path = self._switch_file_extension(input_path, 'ts')
        ffmpeg_command.set_as_argument('OUTPUT', output_path)

        """
        set log output
        """
        if self._log_folder:
            from os.path import splitext, basename, extsep
            mp42ts_log_file_path = self._log_folder \
                                 + PATH_SEPARATOR \
                                 + 'mp42ts_' \
                                 + splitext(basename(input_path))[0] \
                                 + extsep \
                                 + 'log'

            ffmpeg_command.set_as_log_file(mp42ts_log_file_path) \
                          .set_std_err_redirect_to_file()

        ffmpeg_process = self._cmd(ffmpeg_command)

        if isinstance(ffmpeg_process, Process):
            ffmpeg_process.join()

        return output_path
Exemple #10
0
    def send_stream(self, server, port, stream_mode, codec, is_debug_mode=_GLOBAL_DEBUG_MODE):
        """
        Streams the ffmpeg video to a given server:port by a given protocol.

        :param server: the server to stream to
        :type port: int

        :param port: the port to stream to
        :type server: basestring

        :param stream_mode: the mode how to stream the video
        :type stream_mode: basestring

        :param codec: the codec used for the encoding of the video (required to set bit stream filters)
        :type codec: AbstractCodec

        :param is_debug_mode: True is debug logging is allowed, False otherwise
        :type is_debug_mode: bool
        """

        assert isinstance(server, basestring)
        assert isinstance(port, int)
        assert isinstance(stream_mode, basestring)

        assert stream_mode in HrcTable.VALID_STREAM_MODES

        # build streaming command
        command = Command(APP_PATH)

        """
        -re: play back in real-time
        """
        command.set_as_posix_option('re')
        command.set_as_posix_option('y')

        """
        -i <INPUT_FILE>: defines the input file
        """
        command.set_as_posix_option('i', self._src_path)

        """
        -c:v sets the video codec
        """
        if stream_mode == HrcTable.DB_STREAM_MODE_FIELD_VALUE_MPEGTS_RTP:
            command.set_as_posix_option('c:v', codec.get_library_name()) # for MPEGTS_RTP required!
        else:
            command.set_as_posix_option('c:v', 'copy')

        """
        -an (<OUTPUT>): disable audio output
        """
        command.set_as_posix_option('an')

        """
        -f <FMT> (<INPUT/OUTPUT>): force the input/output file format to <FMT>. In general the output format is
        automatically detected by the given input files, so this option is usually not needed.
        """
        command.set_as_posix_option('f', self.__get_io_file_format(stream_mode))

        """
        -bsf:v <FILTER>: sets a filter operation on the stream
        """
        if stream_mode in (
            HrcTable.DB_STREAM_MODE_FIELD_VALUE_MPEGTS_UDP,
            HrcTable.DB_STREAM_MODE_FIELD_VALUE_MPEGTS_RTP
        ):
            bsf_name = codec.get_bit_stream_filter()
            if bsf_name:
                command.set_as_posix_option('bsf:v', bsf_name)

        if stream_mode == HrcTable.DB_STREAM_MODE_FIELD_VALUE_RAW_RTP:
            """
            -sdp_file <SDP_FILE_PATH>: path where to dump the sdp file content
            """

            # noinspection PyPep8Naming
            from os.path import splitext, extsep as FILE_EXTENSION_SEPARATOR
            (base_path, extension) = splitext(self._src_path)
            command.set_as_posix_option('sdp_file', base_path + FILE_EXTENSION_SEPARATOR + 'sdp')


        """
        address where to send the stream to
        """
        command.set_as_argument('DESTINATION', '%s://%s:%d' % (self.__get_stream_protocol(stream_mode), server, port))

        # TODO only for debug
        # command.set_as_argument('DEST2', 'test.ts');
        # TODO /only for debug

        """
        set the commands log output
        """
        command.set_as_log_file(self._log_file) \
               .set_std_err_redirect_to_file()

        """
        SET DEBUG LOG
        """
        if is_debug_mode:
            command.set_as_posix_option('loglevel', 'debug')

        # execute command
        self._cmd(command)
Exemple #11
0
    def decode_video(self, is_debug_mode=_GLOBAL_DEBUG_MODE):
        """
        Receives a video stream from the given stream configuration and returns a process which is able to decode
        this stream

        :param is_debug_mode: True, will allow debug logging of the command, False will disallow this.
        :type is_debug_mode: bool

        :param is_debug_mode: True is debug logging is allowed, False otherwise
        :type is_debug_mode: bool
        """

        command = Command(APP_PATH)

        """
        -y: override without asking
        """
        command.set_as_posix_option('y')

        """
        -i <INPUT>: defines the input stream
        """
        command.set_as_posix_option('i', self._src_path)

        """
        -c:v <CODEC_TYPE>: sets the video codec
        """
        command.set_as_posix_option('c:v', 'rawvideo')

        """
        <OUTPUT>: file where the decoded video should be stored in
        """
        command.set_as_argument('DESTINATION', self._destination_path)

        """
        set commands log output
        """
        command.set_as_log_file(self._log_file) \
               .set_std_err_redirect_to_file()

        """
        SET DEBUG LOG
        """
        if is_debug_mode:
            command.set_as_posix_option('loglevel', 'debug')

        # execute command
        return self._cmd(command)