Example #1
0
def get_video_start_time_blackvue(video_file):
    fd = open(video_file, 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)

    while fd.tell() < eof:
        box = Box.parse_stream(fd)
        if box.type.decode('utf-8') == "moov":
            fd.seek(box.offset + 8, 0)

            size = struct.unpack('>I', fd.read(4))[0]
            typ = fd.read(4)

            fd.seek(4, os.SEEK_CUR)

            creation_time = struct.unpack('>I', fd.read(4))[0]
            modification_time = struct.unpack('>I', fd.read(4))[0]
            time_scale = struct.unpack('>I', fd.read(4))[0]
            duration = struct.unpack('>I', fd.read(4))[0]

            # from documentation
            # in seconds since midnight, January 1, 1904
            video_start_time_epoch = creation_time * 1000 - duration
            epoch_start = datetime.datetime(year=1904, month=1, day=1)
            video_start_time = epoch_start + \
                datetime.timedelta(milliseconds=video_start_time_epoch)
            return video_start_time
Example #2
0
    def ismt_to_ttml(ismt_data):
        fd = io.BytesIO(ismt_data)

        while True:
            x = Box.parse_stream(fd)
            if x.type == b'mdat':
                return x.data
def get_video_start_time_blackvue(video_file):
    with open(video_file, 'rb') as fd:
        fd.seek(0, io.SEEK_END)
        eof = fd.tell()
        fd.seek(0)

        while fd.tell() < eof:
            box = Box.parse_stream(fd)
            if box.type.decode('utf-8') == "moov":
                fd.seek(box.offset + 8, 0)

                size = struct.unpack('>I', fd.read(4))[0]
                typ = fd.read(4)

                fd.seek(4, os.SEEK_CUR)

                creation_time = struct.unpack('>I', fd.read(4))[0]
                modification_time = struct.unpack('>I', fd.read(4))[0]
                time_scale = struct.unpack('>I', fd.read(4))[0]
                duration = struct.unpack('>I', fd.read(4))[0]

                # from documentation
                # in seconds since midnight, January 1, 1904
                video_start_time_epoch = creation_time * 1000 - duration
                epoch_start = datetime.datetime(year=1904, month=1, day=1)
                video_start_time = epoch_start + \
                    datetime.timedelta(milliseconds=video_start_time_epoch)
                return video_start_time
Example #4
0
def decrypt(key, inp, out):
    """
    decrypt()

    @param key: AES-128 CENC key in bytes
    @param inp: Open input file
    @param out: Open output file
    """

    with BufferedReader(inp) as reader:
        senc_boxes = deque()
        trun_boxes = deque()

        while reader.peek(1):
            box = Box.parse_stream(reader)
            fix_headers(box)

            for stsd_box in BoxUtil.find(box, b'stsz'):
                sample_size = stsd_box.sample_size

            if box.type == b'moof':
                senc_boxes.extend(BoxUtil.find(box, b'senc'))
                trun_boxes.extend(BoxUtil.find(box, b'trun'))
            elif box.type == b'mdat':
                senc_box = senc_boxes.popleft()
                trun_box = trun_boxes.popleft()

                clear_box = b''

                with BytesIO(box.data) as box_bytes:
                    for sample, sample_info in zip(
                            senc_box.sample_encryption_info,
                            trun_box.sample_info):
                        counter = Counter.new(64,
                                              prefix=sample.iv,
                                              initial_value=0)

                        cipher = AES.new(key, AES.MODE_CTR, counter=counter)

                        if sample_size:
                            cipher_bytes = box_bytes.read(sample_size)
                            clear_box += cipher.decrypt(cipher_bytes)
                        elif not sample.subsample_encryption_info:
                            cipher_bytes = box_bytes.read(
                                sample_info.sample_size)
                            clear_box += cipher.decrypt(cipher_bytes)
                        else:
                            for subsample in sample.subsample_encryption_info:
                                clear_box += box_bytes.read(
                                    subsample.clear_bytes)
                                cipher_bytes = box_bytes.read(
                                    subsample.cipher_bytes)
                                clear_box += cipher.decrypt(cipher_bytes)
                box.data = clear_box
            out.write(Box.build(box))
    return
Example #5
0
def dump():
    parser = argparse.ArgumentParser(description='Dump all the boxes from an MP4 file')
    parser.add_argument("input_file", type=argparse.FileType("rb"), metavar="FILE", help="Path to the MP4 file to open")

    args = parser.parse_args()

    fd = args.input_file
    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)

    while fd.tell() < eof:
        box = Box.parse_stream(fd)
        print(box)
def find_camera_model(videos_folder):
    from mapillary_tools.uploader import get_video_file_list

    file_list = get_video_file_list(videos_folder)

    fd = open(file_list[0], "rb")

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    while fd.tell() < eof:
        box = Box.parse_stream(fd)
        if box.type.decode("utf-8") == "free":  # or 'ftyp':
            return box.data[29:39]
def find_camera_model(videos_folder) -> bytes:
    from mapillary_tools.uploader import get_video_file_list

    file_list = get_video_file_list(videos_folder)
    if not file_list:
        raise RuntimeError(f"No video found in {videos_folder}")

    fd = open(file_list[0], "rb")

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    while fd.tell() < eof:
        box = Box.parse_stream(fd)
        if box.type.decode("utf-8") == "free":  # or 'ftyp':
            return box.data[29:39]
    raise RuntimeError(f"camera model not found in {file_list[0]}")
Example #8
0
 def test_parse_video_samples(self):
     infile = open('3.cmfv', 'rb')
     moov_box = []
     moof_box = []
     for i in range(5):
         t = Box.parse_stream(infile)
         if (t["type"] == b"moov"):
             moov_box = t
         if (t["type"] == b"moof"):
             moof_box = t
     res = BoxUtil.find_samples_fragmented(moov_box, moof_box, 1)
     self.assertEqual(res[0]["decode_time"], 12288)
     self.assertEqual(res[1]["decode_time"], 12800)
     self.assertEqual(res[2]["decode_time"], 13312)
     self.assertEqual(res[0]["offset_mdat"], 8)
     self.assertEqual(res[1]["offset_mdat"], 2223)
     self.assertEqual(res[2]["offset_mdat"], 2400)
def find_camera_model(videos_folder):
    from mapillary_tools.uploader import get_video_file_list

    file_list = get_video_file_list(videos_folder)

    fd = open(file_list[0], 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    while fd.tell() < eof:
        try:
            box = Box.parse_stream(fd)
        except RangeError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)
        except ConstError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)

        if box.type.decode('utf-8') == 'free':# or 'ftyp':     
            return box.data[29:39]
Example #10
0
def find_camera_model(videos_folder):
    from mapillary_tools.uploader import get_video_file_list

    file_list = get_video_file_list(videos_folder)

    fd = open(file_list[0], 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    while fd.tell() < eof:
        try:
            box = Box.parse_stream(fd)
        except RangeError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)
        except ConstError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)

        if box.type.decode('utf-8') == 'free':  # or 'ftyp':
            return box.data[29:39]
Example #11
0
def get_points_from_bv(path, use_nmea_stream_timestamp=False):
    points = []

    fd = open(path, 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    date = None

    first_gps_date = None
    first_gps_time = None
    found_first_gps_date = False
    found_first_gps_time = False

    while fd.tell() < eof:
        try:
            box = Box.parse_stream(fd)
        except RangeError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)
        except ConstError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)

        if box.type.decode('utf-8') == 'free':
            length = len(box.data)
            offset = 0
            while offset < length:
                newb = Box.parse(box.data[offset:])
                if newb.type.decode('utf-8') == 'gps':
                    lines = newb.data

                    # Parse GPS trace
                    for l in lines.splitlines():
                        m = l.lstrip('[]0123456789')
                        # this utc millisecond timestamp seems to be the camera's
                        # todo: unused?
                        # match = re.search('\[([0-9]+)\]', l)
                        # if match:
                        #     utcdate = match.group(1)

                        #By default, use camera timestamp. Only use GPS Timestamp if camera was not set up correctly and date/time is wrong
                        if use_nmea_stream_timestamp == False:
                            if "$GPGGA" in m:
                                match = re.search('\[([0-9]+)\]', l)
                                if match:
                                    epoch_in_local_time = match.group(1)

                                camera_date = datetime.datetime.utcfromtimestamp(
                                    int(epoch_in_local_time) / 1000.0)
                                data = pynmea2.parse(m)
                                if (data.is_valid):
                                    if found_first_gps_time == False:
                                        first_gps_time = data.timestamp
                                        found_first_gps_time = True
                                    lat, lon, alt = data.latitude, data.longitude, data.altitude
                                    points.append((camera_date, lat, lon, alt))

                        if use_nmea_stream_timestamp == True or found_first_gps_date == False:
                            if "GPRMC" in m:
                                try:
                                    data = pynmea2.parse(m)
                                    if data.is_valid:
                                        date = data.datetime.date()
                                        if found_first_gps_date == False:
                                            first_gps_date = date
                                except pynmea2.ChecksumError as e:
                                    # There are often Checksum errors in the GPS stream, better not to show errors to user
                                    pass
                                except Exception as e:
                                    print(
                                        "Warning: Error in parsing gps trace to extract date information, nmea parsing failed"
                                    )
                        if use_nmea_stream_timestamp == True:
                            if "$GPGGA" in m:
                                try:
                                    data = pynmea2.parse(m)
                                    if (data.is_valid):
                                        lat, lon, alt = data.latitude, data.longitude, data.altitude
                                        if not date:
                                            timestamp = data.timestamp
                                        else:
                                            timestamp = datetime.datetime.combine(
                                                date, data.timestamp)
                                        points.append(
                                            (timestamp, lat, lon, alt))

                                except Exception as e:
                                    print(
                                        "Error in parsing gps trace to extract time and gps information, nmea parsing failed due to {}"
                                        .format(e))

                    #If there are no points after parsing just return empty vector
                    if points == []:
                        return []
                    #After parsing all points, fix timedate issues
                    if use_nmea_stream_timestamp == False:
                        # If we use the camera timestamp, we need to get the timezone offset, since Mapillary backend expects UTC timestamps
                        first_gps_timestamp = datetime.datetime.combine(
                            first_gps_date, first_gps_time)
                        delta_t = points[0][0] - first_gps_timestamp
                        if delta_t.days > 0:
                            hours_diff_to_utc = round(delta_t.total_seconds() /
                                                      3600)
                        else:
                            hours_diff_to_utc = round(
                                delta_t.total_seconds() / 3600) * -1
                        utc_points = []
                        for idx, point in enumerate(points):
                            delay_compensation = datetime.timedelta(
                                seconds=-1.8
                            )  #Compensate for solution age when location gets timestamped by camera clock. Value is empirical from various cameras/recordings
                            new_timestamp = points[idx][0] + datetime.timedelta(
                                hours=hours_diff_to_utc) + delay_compensation
                            lat = points[idx][1]
                            lon = points[idx][2]
                            alt = points[idx][3]
                            utc_points.append((new_timestamp, lat, lon, alt))

                        points = utc_points
                        points.sort()

                    else:
                        #add date to points that don't have it yet, because GPRMC message came later
                        utc_points = []
                        for idx, point in enumerate(points):
                            if type(points[idx][0]) != type(
                                    datetime.datetime.today()):
                                timestamp = datetime.datetime.combine(
                                    first_gps_date, points[idx][0])
                            else:
                                timestamp = points[idx][0]
                            lat = points[idx][1]
                            lon = points[idx][2]
                            alt = points[idx][3]
                            utc_points.append((timestamp, lat, lon, alt))

                        points = utc_points
                        points.sort()

                offset += newb.end

            break

    return points
def get_points_from_bv(path,use_nmea_stream_timestamp=False):
    points = []
    with open(path, 'rb') as fd:

        fd.seek(0, io.SEEK_END)
        eof = fd.tell()
        fd.seek(0)
        date = None

        first_gps_date = None
        first_gps_time = None
        found_first_gps_date = False
        found_first_gps_time = False

        while fd.tell() < eof:
            try:
                box = Box.parse_stream(fd)
            except RangeError:
                print('error parsing blackvue GPS information, exiting')
                sys.exit(1)
            except ConstError:
                print('error parsing blackvue GPS information, exiting')
                sys.exit(1)

            if box.type.decode('utf-8') == 'free':
                length = len(box.data)
                offset = 0
                while offset < length:
                    newb = Box.parse(box.data[offset:])
                    if newb.type.decode('utf-8') == 'gps':
                        lines = newb.data

                        # Parse GPS trace
                        for l in lines.splitlines():
                            m = l.lstrip('[]0123456789')
                            # this utc millisecond timestamp seems to be the camera's
                            # todo: unused?
                            # match = re.search('\[([0-9]+)\]', l)
                            # if match:
                            #     utcdate = match.group(1)
                            
                            #By default, use camera timestamp. Only use GPS Timestamp if camera was not set up correctly and date/time is wrong
                            if use_nmea_stream_timestamp==False:
                                if "$GPGGA" in m:
                                    match = re.search('\[([0-9]+)\]', l)
                                    if match:
                                        epoch_in_local_time = match.group(1)

                                    camera_date=datetime.datetime.utcfromtimestamp(int(epoch_in_local_time)/1000.0)
                                    data = pynmea2.parse(m)
                                    if(data.is_valid):
                                        if  found_first_gps_time == False:
                                            first_gps_time = data.timestamp
                                            found_first_gps_time = True
                                        lat, lon, alt = data.latitude, data.longitude, data.altitude
                                        points.append((camera_date, lat, lon, alt))

                            if use_nmea_stream_timestamp==True or found_first_gps_date==False:
                                if "GPRMC" in m:
                                    try:
                                        data = pynmea2.parse(m)
                                        if data.is_valid:
                                            date = data.datetime.date()
                                            if found_first_gps_date == False:
                                                first_gps_date=date
                                    except pynmea2.ChecksumError as e:
                                        # There are often Checksum errors in the GPS stream, better not to show errors to user
                                        pass
                                    except Exception as e:
                                        print(
                                            "Warning: Error in parsing gps trace to extract date information, nmea parsing failed")
                            if use_nmea_stream_timestamp==True:
                                if "$GPGGA" in m:
                                    try:
                                        data = pynmea2.parse(m)
                                        if(data.is_valid):
                                            lat, lon, alt = data.latitude, data.longitude, data.altitude
                                            if not date:
                                                timestamp = data.timestamp
                                            else:
                                                timestamp = datetime.datetime.combine(
                                                date, data.timestamp)
                                            points.append((timestamp, lat, lon, alt))

                                    except Exception as e:
                                        print(
                                            "Error in parsing gps trace to extract time and gps information, nmea parsing failed due to {}".format(e))
                        
                        #If there are no points after parsing just return empty vector
                        if points == []:
                            return []
                        #After parsing all points, fix timedate issues
                        if use_nmea_stream_timestamp==False:
                            # If we use the camera timestamp, we need to get the timezone offset, since Mapillary backend expects UTC timestamps
                            first_gps_timestamp = datetime.datetime.combine(first_gps_date, first_gps_time)
                            delta_t = points[0][0]-first_gps_timestamp
                            if delta_t.days>0:
                                hours_diff_to_utc = round(delta_t.total_seconds()/3600)
                            else:
                                hours_diff_to_utc = round(delta_t.total_seconds()/3600) * -1
                            utc_points=[]
                            for idx, point in enumerate(points):
                                delay_compensation = datetime.timedelta(seconds=-1.8) #Compensate for solution age when location gets timestamped by camera clock. Value is empirical from various cameras/recordings
                                new_timestamp = points[idx][0]+datetime.timedelta(hours=hours_diff_to_utc)+delay_compensation
                                lat = points[idx][1]
                                lon = points[idx][2]
                                alt = points[idx][3]
                                utc_points.append((new_timestamp, lat, lon, alt))

                            points = utc_points
                            points.sort()

                        else:
                            #add date to points that don't have it yet, because GPRMC message came later 
                            utc_points=[]
                            for idx, point in enumerate(points):
                                if type(points[idx][0]) != type(datetime.datetime.today()):
                                    timestamp = datetime.datetime.combine(
                                            first_gps_date, points[idx][0])
                                else:
                                    timestamp = points[idx][0]                                    
                                lat = points[idx][1]
                                lon = points[idx][2]
                                alt = points[idx][3]
                                utc_points.append((timestamp, lat, lon, alt))

                            points = utc_points
                            points.sort()

                    offset += newb.end

                break

        return points
def get_points_from_bv(path):
    points = []

    fd = open(path, 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    date = None
    while fd.tell() < eof:
        try:
            box = Box.parse_stream(fd)
        except RangeError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)
        except ConstError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)

        if box.type.decode('utf-8') == 'free':
            length = len(box.data)
            offset = 0
            while offset < length:
                newb = Box.parse(box.data[offset:])
                if newb.type.decode('utf-8') == 'gps':
                    lines = newb.data

                    for l in lines:
                        if "GPRMC" in l:
                            m = l.lstrip('[]0123456789')
                            try:
                                data = pynmea2.parse(m)
                                date = data.datetime.date()
                            except Exception as e:
                                print(
                                    "Error in extracting the gps trace, nmea parsing failed due to {}"
                                    .format(e))
                            break

                    # Parse GPS trace
                    for l in lines.splitlines():
                        # this utc millisecond timestamp seems to be the camera's
                        # todo: unused?
                        # match = re.search('\[([0-9]+)\]', l)
                        # if match:
                        #     utcdate = match.group(1)

                        m = l.lstrip('[]0123456789')

                        if "GPRMC" in m:
                            try:
                                data = pynmea2.parse(m)
                                date = data.datetime.date()
                            except Exception as e:
                                print(
                                    "Error in parsing gps trace to extract date information, nmea parsing failed due to {}"
                                    .format(e))
                        if "$GPGGA" in m:
                            try:
                                if not date:
                                    print(
                                        "Error, could not extract date from the video gps trace, exiting..."
                                    )
                                    sys.exit(1)
                                data = pynmea2.parse(m)
                                timestamp = datetime.datetime.combine(
                                    date, data.timestamp)
                                lat, lon, alt = data.latitude, data.longitude, data.altitude
                                points.append((timestamp, lat, lon, alt))
                            except Exception as e:
                                print(
                                    "Error in parsing gps trace to extract time and gps information, nmea parsing failed due to {}"
                                    .format(e))

                    points.sort()
                offset += newb.end

            break

    return points
Example #14
0
def dump(file, dump_embedded, dump_raw_blocks, extended_scan, verbose):
    """ Extract GPS and Acceleration data from BlackVue MP4 recordings.

    BlackVue extracts data embedded in the MP4 recordings of a BlackVue Dashcam.
    """
    for filename in file:
        filebase = os.path.splitext(filename)[0]
        with open(filename, 'rb') as fd:
            fd.seek(0, io.SEEK_END)
            eof = fd.tell()
            fd.seek(0)

            while fd.tell() < eof:
                try:
                    box = Box.parse_stream(fd)
                    # print(box)
                    content = dict(box.__getstate__())
                    ctype = content['type'].decode('utf8')
                    if 'data' in content and ctype == 'free':
                        offset = content['offset']
                        end = content['end']
                        data = content['data']
                        if verbose:
                            print(
                                "Found container of type '{}', data has length {}."
                                .format(ctype, len(data)))
                        if dump_embedded:
                            with open(
                                    filename +
                                    "-{:012d}-{}.bin".format(offset, ctype),
                                    "wb") as ofd:
                                ofd.write(data)
                        idx = 0
                        while idx < len(data):
                            block_len = int.from_bytes(data[idx:idx + 4],
                                                       'big')
                            block_data = data[idx + 4:idx + block_len]
                            if verbose:
                                print("Found block with len {}".format(
                                    block_len))
                            if block_len == 0:
                                break
                            if dump_raw_blocks:
                                with open(
                                        filebase +
                                        "-{:012d}-{}-{:08d}.bin".format(
                                            offset, ctype, idx), "wb") as ofd:
                                    ofd.write(block_data)
                            if block_data[0:4] in emb_file_def:
                                first, has_length, termination, ext = emb_file_def[
                                    block_data[0:4]]

                                # some data like thmb indicates the length:
                                last = first + int.from_bytes(
                                    block_data[4:8],
                                    'big') if has_length else block_len

                                # other data like gps is zero terminated:
                                last = block_data.find(
                                    termination
                                ) if termination is not None else last

                                if ext is not None:
                                    with open(filebase + ext, "wb") as ofd:
                                        ofd.write(block_data[first:last])

                                if ext == '.3gf':
                                    with open(filebase + ext + ".txt",
                                              "wt") as ofd:
                                        n = 0
                                        while first < last:
                                            chunk = block_data[first:first +
                                                               10]
                                            time_ms = int.from_bytes(
                                                chunk[0:4], 'big')
                                            if time_ms == 0xffffffff:
                                                break
                                            acc_1u = int.from_bytes(
                                                chunk[4:6], 'big')
                                            acc_2u = int.from_bytes(
                                                chunk[6:8], 'big')
                                            acc_3u = int.from_bytes(
                                                chunk[8:10], 'big')
                                            acc_1s = int.from_bytes(
                                                chunk[4:6], 'big', signed=True)
                                            acc_2s = int.from_bytes(
                                                chunk[6:8], 'big', signed=True)
                                            acc_3s = int.from_bytes(
                                                chunk[8:10],
                                                'big',
                                                signed=True)
                                            ofd.write(
                                                ("{:8d} " +
                                                 "{:08x} {:04x} {:04x} {:04x} "
                                                 + "{:6d} {:6d} {:6d} {:6d}\n"
                                                 ).format(
                                                     n, time_ms, acc_1u,
                                                     acc_2u, acc_3u, time_ms,
                                                     acc_1s, acc_2s, acc_3s))
                                            first += 10
                                            n += 1

                            idx += block_len
                        if verbose:
                            ("Got to idx {}.".format(idx))
                        if not extended_scan:
                            break

                except construct.core.ConstError:
                    break

                except Exception as e:
                    print(e)
                    raise
Example #15
0
def detect_file_type(input_file):
    device = "X"
    make = "unknown"
    model = "unknown"
    if input_file.lower().endswith(".ts"):
        with open(input_file, "rb") as f:
            device = "A"
            input_packet = f.read(188)  #First packet, try to autodetect
            if bytes("\xB0\x0D\x30\x34\xC3", encoding="raw_unicode_escape"
                     ) in input_packet[4:20] or args.device_override == "V":
                device = "V"
                make = "Viofo"
                model = "A119 V3"

            if bytes("\x40\x1F\x4E\x54\x39", encoding="raw_unicode_escape"
                     ) in input_packet[4:20] or args.device_override == "B":
                device = "B"
                make = "Blueskysea"
                model = "B4K"

            while device == "A":
                currentdata = {}
                input_packet = f.read(188)
                if not input_packet:
                    break

                #Autodetect camera type
                if device == 'A' and input_packet.startswith(
                        bytes("\x47\x03\x00", encoding="raw_unicode_escape")):
                    bs = list(input_packet)
                    active = chr(bs[156])
                    lathem = chr(bs[157])
                    lonhem = chr(bs[158])
                    if lathem in "NS" and lonhem in "EW":
                        device = "B"
                        make = "Blueskysea"
                        model = "B4K"
                        print("Autodetected as Blueskysea B4K")
                        break

                if device == 'A' and input_packet.startswith(
                        bytes("\x47\x43\x00", encoding="raw_unicode_escape")):
                    bs = list(input_packet)
                    active = chr(bs[34])
                    lathem = chr(bs[35])
                    lonhem = chr(bs[36])
                    if lathem in "NS" and lonhem in "EW":
                        device = "V"
                        print("Autodetected as Viofo A119 V3")
                        make = "Viofo"
                        model = "A119 V3"
                        break
    if input_file.lower().endswith(
            ".mp4"):  #Guess which MP4 method is used: Novatek, Subtitle, NMEA
        with open(input_file, "rb") as fx:

            if True:
                fx.seek(0, io.SEEK_END)
                eof = fx.tell()
                fx.seek(0)
                lines = []
                while fx.tell() < eof:
                    try:
                        box = Box.parse_stream(fx)
                    except:
                        pass
                    #print (box.type.decode("utf-8"))
                    if box.type.decode("utf-8") == "free":
                        length = len(box.data)
                        offset = 0
                        while offset < length:
                            inp = Box.parse(box.data[offset:])
                            #print (inp.type.decode("utf-8"))
                            if inp.type.decode("utf-8") == "gps":  #NMEA-based
                                lines = inp.data
                                for line in lines.splitlines():
                                    m = str(line).lstrip("[]0123456789")
                                    if "$GPGGA" in m:
                                        device = "N"
                                        make = "NMEA-based video"
                                        model = "unknown"
                                        break
                            offset += inp.end
                    if box.type.decode(
                            "utf-8") == "gps":  #has Novatek-specific stuff
                        fx.seek(0)
                        largeelem = fx.read()
                        startbytes = [
                            m.start()
                            for m in re.finditer(b'freeGPS', largeelem)
                        ]
                        del largeelem
                        if len(startbytes) > 0:
                            make = "Novatek"
                            model = "MP4"
                            device = "T"
                            break

                    if box.type.decode("utf-8") == "moov":
                        try:
                            length = len(box.data)
                        except:
                            length = 0
                        offset = 0
                        while offset < length:
                            inp = Box.parse(box.data[offset:])
                            #print (inp.type.decode("utf-8"))
                            if inp.type.decode("utf-8") == "gps":  #NMEA-based
                                lines = inp.data
                                print(len(inp.data))
                                for line in lines.splitlines():
                                    m = str(line).lstrip("[]0123456789")
                                    if "$GPGGA" in m:
                                        device = "N"
                                        make = "NMEA-based video"
                                        model = "unknown"
                                        #break
                            offset += inp.end
            else:
                pass
            if device == "X":
                fx.seek(0)
                largeelem = fx.read()
                startbytes = [
                    m.start() for m in re.finditer(
                        b'\x00\x14\x50\x4E\x44\x4D\x00\x00\x00\x00', largeelem)
                ]
                del largeelem
                if len(startbytes) > 0:
                    make = "Garmin"
                    model = "unknown"
                    device = "G"
            if device == "X":
                fx.seek(0)
                largeelem = fx.read()
                startbytes = [
                    m.start() for m in re.finditer(b'GPGGA', largeelem)
                ]

                del largeelem
                if len(startbytes) > 0:
                    make = "NEXTBASE"
                    model = "unknown"
                    device = "NB"
    return device, make, model
Example #16
0
def get_gps_data_nmea(input_file, device):
    packetno = 0
    locdata = {}
    with open(input_file, "rb") as fx:
        if True:
            fx.seek(0, io.SEEK_END)
            eof = fx.tell()
            fx.seek(0)
            prevts = 0
            lines = []
            while fx.tell() < eof:
                try:
                    box = Box.parse_stream(fx)
                except:
                    pass
                if box.type.decode("utf-8") == "free":
                    try:
                        length = len(box.data)
                    except:
                        length = 0
                    offset = 0
                    while offset < length:
                        inp = Box.parse(box.data[offset:])
                        #print (inp.type.decode("utf-8"))
                        if inp.type.decode("utf-8") == "gps":  #NMEA-based

                            lines = inp.data

                            for line in lines.splitlines():
                                m = str(line)
                                if "$GPRMC" in m:
                                    currentdata = {}
                                    currentdata["ts"] = int(m[3:13])
                                    #print (m)
                                    try:
                                        currentdata["lat"] = float(
                                            m.split(",")[3][0:2]) + float(
                                                m.split(",")[3][2:]) / 60
                                        currentdata["latR"] = m.split(",")[4]
                                        if currentdata["latR"] == "S":
                                            currentdata[
                                                "lat"] = -currentdata["lat"]

                                        currentdata["lon"] = float(
                                            m.split(",")[5][0:3]) + float(
                                                m.split(",")[5][3:]) / 60
                                        currentdata["lonR"] = m.split(",")[6]
                                        if currentdata["lonR"] == "N":
                                            currentdata[
                                                "lon"] = -currentdata["lon"]
                                    except:
                                        pass
                                    try:
                                        currentdata["bearing"] = float(
                                            m.split(",")[9])
                                        currentdata["speed"] = float(
                                            m.split(",")[8]) * 1.6 / 3.6

                                    except:
                                        currentdata["bearing"] = 0
                                        currentdata["speed"] = 0
                                    active = (m.split(",")[2])
                                    nts = currentdata["ts"]

                                    currentdata["metric"] = 0
                                    currentdata["prevdist"] = 0
                                    try:
                                        currentdata["mx"], currentdata[
                                            "my"] = lonlat_metric(
                                                currentdata["lon"],
                                                currentdata["lat"])
                                    except:
                                        pass

                                    if active == "A" and nts > prevts:
                                        locdata[packetno] = currentdata
                                        prevts = nts
                                        packetno += 1

                                    del currentdata
                        offset += inp.end
    return locdata, packetno
def get_points_from_bv(path,use_nmea_stream_timestamp=False):
    points = []

    fd = open(path, 'rb')

    fd.seek(0, io.SEEK_END)
    eof = fd.tell()
    fd.seek(0)
    date = None
    while fd.tell() < eof:
        try:
            box = Box.parse_stream(fd)
        except RangeError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)
        except ConstError:
            print('error parsing blackvue GPS information, exiting')
            sys.exit(1)

        if box.type.decode('utf-8') == 'free':
            length = len(box.data)
            offset = 0
            while offset < length:
                newb = Box.parse(box.data[offset:])
                if newb.type.decode('utf-8') == 'gps':
                    lines = newb.data

                    # Parse GPS trace
                    for l in lines.splitlines():
                        # this utc millisecond timestamp seems to be the camera's
                        # todo: unused?
                        # match = re.search('\[([0-9]+)\]', l)
                        # if match:
                        #     utcdate = match.group(1)

                        #By default, use camera timestamp. Only use GPS Timestamp if camera was not set up correctly and date/time is wrong
                        if use_nmea_stream_timestamp==False:
                            m = l.lstrip('[]0123456789')
                            if "$GPGGA" in m:
                                match = re.search('\[([0-9]+)\]', l)
                                if match:
                                    utcdate = match.group(1)

                                date=datetime.datetime.utcfromtimestamp(int(utcdate)/1000.0)
                                data = pynmea2.parse(m)
                                if(data.is_valid):
                                    lat, lon, alt = data.latitude, data.longitude, data.altitude
                                    points.append((date, lat, lon, alt))

                        else:
                            if "GPRMC" in m:
                                try:
                                    data = pynmea2.parse(m)
                                    date = data.datetime.date()
                                except Exception as e:
                                    print(
                                        "Error in parsing gps trace to extract date information, nmea parsing failed due to {}".format(e))
                            
                            if "$GPGGA" in m:
                                try:
                                    if not date:
                                        #discarding Lat/Lon messages if date has not been set yet. TODO: we could save the messages and add the date later
                                        continue 
                                    data = pynmea2.parse(m)
                                    if(data.is_valid):
                                        timestamp = datetime.datetime.combine(
                                            date, data.timestamp)
                                        lat, lon, alt = data.latitude, data.longitude, data.altitude
                                        points.append((timestamp, lat, lon, alt))
                                except Exception as e:
                                    print(
                                        "Error in parsing gps trace to extract time and gps information, nmea parsing failed due to {}".format(e))

                    points.sort()
                offset += newb.end

            break

    return points
    def read(self) -> Telemetry:
        tel = Telemetry()
        with open(self.source, 'rb') as fd:

            fd.seek(0, io.SEEK_END)
            eof = fd.tell()
            fd.seek(0)

            while fd.tell() < eof:
                try:
                    box = Box.parse_stream(fd)
                except RangeError:
                    print('error parsing blackvue GPS information, exiting')
                    sys.exit(1)
                except ConstError:
                    print('error parsing blackvue GPS information, exiting')
                    sys.exit(1)

                if box.type.decode('utf-8') == 'free':
                    length = len(box.data)
                    offset = 0
                    while offset < length:
                        newb = Box.parse(box.data[offset:])
                        if newb.type.decode('utf-8') == 'gps':
                            lines = newb.data.decode('utf-8')

                            # Parse GPS trace
                            timestamp = None
                            packet = None
                            for l in lines.splitlines():
                                m = l.lstrip('[]0123456789')
                                if not m:
                                    continue

                                match = re.search('\[([0-9]+)\]', l)
                                # If new timestamp found
                                if match and match.group(1) != timestamp:
                                    if packet:
                                        tel.append(packet)
                                    packet = Packet()
                                    timestamp = match.group(1)
                                    packet[TimestampElement.
                                           name] = TimestampElement(
                                               float(timestamp) * 1e-3)

                                #remove timestamp on tail if it exists
                                try:
                                    m = m[:m.rindex('[')]
                                except:
                                    pass

                                try:
                                    m = m[:m.index("\x00")]
                                except:
                                    pass

                                try:
                                    nmea_data = pynmea2.parse(m)
                                    if nmea_data and nmea_data.sentence_type == 'GGA':
                                        packet[LatitudeElement.
                                               name] = LatitudeElement(
                                                   nmea_data.latitude)
                                        packet[LongitudeElement.
                                               name] = LongitudeElement(
                                                   nmea_data.longitude)
                                        if nmea_data.altitude:
                                            packet[AltitudeElement.
                                                   name] = AltitudeElement(
                                                       nmea_data.altitude)
                                    if nmea_data and nmea_data.sentence_type == 'VTG':
                                        packet[
                                            SpeedElement.name] = SpeedElement(
                                                nmea_data.spd_over_grnd_kmph /
                                                3.6)  #convert to m/s
                                except:
                                    self.logger.warn(
                                        "Couldn't parse nmea sentence. Skipping..."
                                    )

                            if packet:
                                tel.append(packet)
                        offset += newb.end
                    break

            return tel