def test_parse_emsg(self): emsg1 = Box.parse(self.l_emsg1) self.assertEqual(emsg1["type"], b'emsg') self.assertEqual(emsg1["version"], 0) self.assertEqual(emsg1["id"], 811) self.assertEqual(emsg1["event_duration"], 233472) self.assertEqual(emsg1["scheme_id_uri"], b'urn:scte:scte35:2013:bin') self.assertEqual( emsg1["message_data"], b'\xfc0!\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x10\x05\x00\x00\x03+\x7f\xef\x7f\xfe\x00\x1a\x17\xb0\xc0\x00\x00\x00\x00\x00\xe4a$\x02' ) emsg2 = Box.parse(self.l_emsg2) self.assertEqual(emsg2["type"], b'emsg') self.assertEqual(emsg2["version"], 0) self.assertEqual(emsg2["id"], 812) self.assertEqual(emsg2["event_duration"], 233472) self.assertEqual(emsg2["scheme_id_uri"], b'urn:scte:scte35:2013:bin') self.assertEqual( emsg2["message_data"], b'\xfc0!\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x10\x05\x00\x00\x03,\x7f\xef\x7f\xfe\x00\x1a\x17\xb0\xc0\x00\x00\x00\x00\x00\xfe\xcc\xb92' ) embe1 = Box.parse(self.l_embe) self.assertEqual(embe1["type"], b'embe')
def test_smhd_parse(self): in_bytes = b'\x00\x00\x00\x10smhd\x00\x00\x00\x00\x00\x00\x00\x00' self.assertEqual( Box.parse(in_bytes + b'padding'), Container(offset=0) (type=b"smhd")(version=0)(flags=0) (balance=0)(reserved=0)(end=len(in_bytes)) )
def test_mdhd_parse(self): self.assertEqual( Box.parse( b'\x00\x00\x00\x20mdhd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fB@\x00\x00\x00\x00U\xc4\x00\x00' ), Container(offset=0)(type=b"mdhd")(version=0)(flags=0)( creation_time=0)(modification_time=0)(timescale=1000000)( duration=0)(language="und")(end=32))
def test_stsd_parse(self): tx3g_data = b'\x00\x00\x00\x00\x01\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x12\xFF\xFF\xFF\xFF\x00\x00\x00\x12ftab\x00\x01\x00\x01\x05Serif' in_bytes = b'\x00\x00\x00\x50stsd\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x40tx3g\x00\x00\x00\x00\x00\x00\x00\x01' + tx3g_data self.assertEqual( Box.parse(in_bytes + b'padding'), Container(offset=0)(type=b"stsd")(version=0)(flags=0)(entries=[ Container(format=b'tx3g')(data_reference_index=1)( data=tx3g_data) ])(end=len(in_bytes)))
def test_parse_stsd_urim(self): urim_sample_entry = Box.parse(self.l_stsd_emsg1) self.assertEqual(len(urim_sample_entry["entries"]), 1) for entry in urim_sample_entry["entries"]: self.assertEqual(entry["format"], b"urim") for l_child in entry["children"]: if l_child["type"] != b"uriI": self.assertEqual(l_child["type"][0:3], b'uri') self.assertEqual(l_child["theURI"], b"urn:mpeg:dash:event:2012")
def test_ftyp_parse(self): self.assertEqual( Box.parse(b'\x00\x00\x00\x18ftypiso5\x00\x00\x00\x01iso5avc1'), Container(offset=0) (type=b"ftyp") (major_brand=b"iso5") (minor_version=1) (compatible_brands=[b"iso5", b"avc1"]) (end=24) )
def test_tenc_parse(self): self.assertEqual( Box.parse(b'\x00\x00\x00 tenc\x00\x00\x00\x00\x00\x00\x01\x083{\x96C!\xb6CU\x9eY>\xcc\xb4l~\xf7'), Container(offset=0) (type=b"tenc") (version=0) (flags=0) (is_encrypted=1) (iv_size=8) (key_ID=UUID('337b9643-21b6-4355-9e59-3eccb46c7ef7')) (end=32) )
def test_parse_trun(self): trun_box1 = Box.parse(self.l_trun_emsg) self.assertEqual(trun_box1["type"], b'trun') self.assertEqual(trun_box1["version"], 0) self.assertEqual( trun_box1["flags"]["sample_composition_time_offsets_present"], False) self.assertEqual(trun_box1["flags"]["sample_flags_present"], False) self.assertEqual(trun_box1["flags"]["sample_size_present"], True) self.assertEqual(trun_box1["flags"]["sample_duration_present"], True) self.assertEqual(trun_box1["flags"]["first_sample_flags_present"], False) self.assertEqual(trun_box1["flags"]["data_offset_present"], True) self.assertEqual(trun_box1["sample_count"], 1) self.assertEqual(trun_box1["data_offset"], 112) self.assertEqual(len(trun_box1["sample_info"]), 1) self.assertEqual(trun_box1["sample_info"][0]["sample_duration"], 25600) self.assertEqual(trun_box1["sample_info"][0]["sample_size"], 8) trun_box2 = Box.parse(self.l_trun2_emsg) self.assertEqual(trun_box2["type"], b'trun') self.assertEqual(trun_box2["version"], 0) self.assertEqual( trun_box2["flags"]["sample_composition_time_offsets_present"], False) self.assertEqual(trun_box2["flags"]["sample_flags_present"], False) self.assertEqual(trun_box2["flags"]["sample_size_present"], True) self.assertEqual(trun_box2["flags"]["sample_duration_present"], True) self.assertEqual(trun_box2["flags"]["first_sample_flags_present"], False) self.assertEqual(trun_box2["flags"]["data_offset_present"], True) self.assertEqual(trun_box2["sample_count"], 1) self.assertEqual(trun_box2["data_offset"], 112) self.assertEqual(len(trun_box2["sample_info"]), 1) self.assertEqual(trun_box2["sample_info"][0]["sample_duration"], 233472) self.assertEqual(trun_box2["sample_info"][0]["sample_size"], 90)
def test_parse_edit_list(self): elst_b = Box.parse( b'\x00\x00\x00\x1celst\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x0f\xa0\x00\x00\x04\x00\x00\x01\x00\x00' ) [Container(edit_duration=4000)(media_time=1024)] self.assertEqual(elst_b["type"], b"elst") self.assertEqual(len(elst_b["entries"]), 1) self.assertEqual(elst_b["entries"][0]["edit_duration"], 4000) self.assertEqual(elst_b["entries"][0]["media_time"], 1024) self.assertEqual(elst_b["entries"][0]["media_rate_integer"], 1) self.assertEqual(elst_b["entries"][0]["media_rate_fraction"], 0) t = dict( type=b"elst", version=1, flags=0, entries=[dict(edit_duration=1,media_time=1, media_rate_integer=1, media_rate_fraction=1)\ ,dict(edit_duration=2,media_time=2, media_rate_integer=1, media_rate_fraction=1) ], ) elst_b = Box.build(t) t2 = Box.parse(elst_b) self.assertEqual(len(t["entries"]), len(t2["entries"]))
def test_parse_stbl_progressive(self): stbl = Box.parse(l_stbl_audio_4s) self.assertNotEqual(stbl, None) stsd = BoxUtil.find_and_return_first(stbl, b'stsd') self.assertEqual(len(stsd["entries"]), 1) self.assertEqual(stsd["entries"][0]["format"], b"mp4a") mp4a = stsd["entries"][0] self.assertEqual(mp4a["channels"], 2) self.assertEqual(mp4a["sampling_rate"], 48000) stsz = BoxUtil.find_and_return_first(stbl, b'stsz') self.assertNotEqual(stsz, None) self.assertEqual(stsz["sample_count"], 189) stco = BoxUtil.find_and_return_first(stbl, b'stco') self.assertNotEqual(stco, None) self.assertEqual(len(stco["entries"]), 1) stts = BoxUtil.find_and_return_first(stbl, b'stts') self.assertNotEqual(stts, None) self.assertEqual(len(stts["entries"]), 2)
def test_udta_terminator_parse(self): ilst = b'\x00\x00\x00\x25\xA9\x74\x6F\x6F\x00\x00\x00\x1D\x64\x61\x74\x61\x00\x00\x00\x01\x00\x00\x00\x00\x4C\x61\x76\x66\x35\x37\x2E\x32\x35\x2E\x31\x30\x30' input_bytes = ( b'\x00\x00\x00\x66udta' b'\x00\x00\x00\x5ameta\x00\x00\x00\x00' b'\x00\x00\x00\x21hdlr\x00\x00\x00\x00\x00\x00\x00\x00mdir\x61\x70\x70\x6C\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x2Dilst' + ilst + b'\x00\x00\x00\x00') self.assertEqual( Box.parse(input_bytes), Container(offset=0)(type=b'udta')(children=[ Container(offset=8)(type=b'meta')(version=0)(flags=0)( children=[ Container(offset=20)(type=b'hdlr')(version=0)(flags=0)( handler_type=b'mdir')(name=u'')(end=53), Container(offset=53)(type=b'ilst')(data=ilst)( end=len(input_bytes) - 4) ])(end=len(input_bytes) - 4) ])(end=len(input_bytes)))
def test_build_emib(self): emib_b = Box.build( dict(type=b"emib", version=0, reserved=1, presentation_time_delta=-1000, value=b'', id=1, scheme_id_uri=b"my_test_scheme", duration=2000, message_data=b"asdfdasgfaghhgsdgh")) emib_b_p = Box.parse(emib_b) self.assertEqual(emib_b_p["type"], b'emib') self.assertEqual(emib_b_p["presentation_time_delta"], -1000) self.assertEqual(emib_b_p["value"], b'') self.assertEqual(emib_b_p["id"], 1) self.assertEqual(emib_b_p["scheme_id_uri"], b"my_test_scheme") self.assertEqual(emib_b_p["duration"], 2000) self.assertEqual(emib_b_p["reserved"], 1) self.assertEqual(emib_b_p["message_data"], b"asdfdasgfaghhgsdgh")
def test_build_emsg(self): emsg_b = Box.build( dict(type=b"emsg", version=1, presentation_time=1000, value=b'', id=1, scheme_id_uri=b"my_test_scheme", event_duration=20, timescale=1, message_data=b"asdfdasgfaghhgsdgh")) emsg_b_p = Box.parse(emsg_b) self.assertEqual(emsg_b_p["type"], b'emsg') self.assertEqual(emsg_b_p["version"], 1) self.assertEqual(emsg_b_p["presentation_time"], 1000) self.assertEqual(emsg_b_p["value"], b'') self.assertEqual(emsg_b_p["id"], 1) self.assertEqual(emsg_b_p["scheme_id_uri"], b"my_test_scheme") self.assertEqual(emsg_b_p["event_duration"], 20) self.assertEqual(emsg_b_p["timescale"], 1) self.assertEqual(emsg_b_p["message_data"], b"asdfdasgfaghhgsdgh")
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 test_parse_stbl_parse_samples_progressive(self): moov_a = Box.parse(l_movie_box_audio) res = BoxUtil.find_samples_progressive(moov_a, moov_a) self.assertEqual(len(res), 189)
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
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
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
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 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