blob: 6a45fe08d950c04fac09cb649b0c2b034a9d86be [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package google.streetview.publish.v1;
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/type/latlng.proto";
option go_package = "google.golang.org/genproto/googleapis/streetview/publish/v1;publish";
option java_outer_classname = "StreetViewPublishResources";
option java_package = "com.google.geo.ugc.streetview.publish.v1";
// Upload reference for media files.
message UploadRef {
// Required.
oneof file_source {
// An upload reference should be unique for each user. It follows
// the form:
// "https://streetviewpublish.googleapis.com/media/user/{account_id}/photo/{upload_reference}"
string upload_url = 1;
}
}
// Identifier for a [Photo][google.streetview.publish.v1.Photo].
message PhotoId {
// A unique identifier for a photo.
string id = 1;
}
// Level information containing level number and its corresponding name.
message Level {
// Optional. Floor number, used for ordering. 0 indicates the ground level, 1
// indicates the first level above ground level, -1 indicates the first level
// under ground level. Non-integer values are OK.
double number = 1 [(google.api.field_behavior) = OPTIONAL];
// Required. A name assigned to this Level, restricted to 3 characters.
// Consider how the elevator buttons would be labeled for this level if there
// was an elevator.
string name = 2 [(google.api.field_behavior) = REQUIRED];
}
// Raw pose measurement for an entity.
message Pose {
// Latitude and longitude pair of the pose, as explained here:
// https://cloud.google.com/datastore/docs/reference/rest/Shared.Types/LatLng
// When creating a [Photo][google.streetview.publish.v1.Photo], if the
// latitude and longitude pair are not provided, the geolocation from the
// exif header is used. A latitude and longitude pair not provided in the
// photo or exif header causes the photo process to fail.
google.type.LatLng lat_lng_pair = 1;
// Altitude of the pose in meters above WGS84 ellipsoid.
// NaN indicates an unmeasured quantity.
double altitude = 2;
// The following pose parameters pertain to the center of the photo. They
// match https://developers.google.com/streetview/spherical-metadata.
// Compass heading, measured at the center of the photo in degrees clockwise
// from North. Value must be >=0 and <360. NaN indicates an unmeasured
// quantity.
double heading = 3;
// Pitch, measured at the center of the photo in degrees. Value must be >=-90
// and <= 90. A value of -90 means looking directly down, and a value of 90
// means looking directly up.
// NaN indicates an unmeasured quantity.
double pitch = 4;
// Roll, measured in degrees. Value must be >= 0 and <360. A value of 0
// means level with the horizon.
// NaN indicates an unmeasured quantity.
double roll = 5;
// Time of the GPS record since UTC epoch.
google.protobuf.Timestamp gps_record_timestamp_unix_epoch = 6;
// Level (the floor in a building) used to configure vertical navigation.
Level level = 7;
// The estimated horizontal accuracy of this pose in meters with 68%
// confidence (one standard deviation). For example, on Android, this value is
// available from this method:
// https://developer.android.com/reference/android/location/Location#getAccuracy().
// Other platforms have different methods of obtaining similar accuracy
// estimations.
float accuracy_meters = 9;
}
// IMU data from the device sensors.
message Imu {
// A Generic 3d measurement sample.
message Measurement3d {
// The timestamp of the IMU measurement.
google.protobuf.Timestamp capture_time = 1;
// The sensor measurement in the x axis.
float x = 2;
// The sensor measurement in the y axis.
float y = 3;
// The sensor measurement in the z axis.
float z = 4;
}
// The accelerometer measurements in meters/sec^2 with increasing timestamps
// from devices.
repeated Measurement3d accel_mpsps = 1;
// The gyroscope measurements in radians/sec with increasing timestamps from
// devices.
repeated Measurement3d gyro_rps = 2;
// The magnetometer measurements of the magnetic field in microtesla (uT) with
// increasing timestamps from devices.
repeated Measurement3d mag_ut = 3;
}
// Place metadata for an entity.
message Place {
// Place identifier, as described in
// https://developers.google.com/places/place-id.
string place_id = 1;
// Output only. The name of the place, localized to the language_code.
string name = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The language_code that the name is localized with. This should
// be the language_code specified in the request, but may be a fallback.
string language_code = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}
// A connection is the link from a source photo to a destination photo.
message Connection {
// Required. The destination of the connection from the containing photo to
// another photo.
PhotoId target = 1 [(google.api.field_behavior) = REQUIRED];
}
// Photo is used to store 360 photos along with photo metadata.
message Photo {
// Status of rights transfer.
enum TransferStatus {
// The status of this transfer is unspecified.
TRANSFER_STATUS_UNKNOWN = 0;
// This photo has never been in a transfer.
NEVER_TRANSFERRED = 1;
// This photo transfer has been initiated, but the receiver has not yet
// responded.
PENDING = 2;
// The photo transfer has been completed, and this photo has been
// transferred to the recipient.
COMPLETED = 3;
// The recipient rejected this photo transfer.
REJECTED = 4;
// The photo transfer expired before the recipient took any action.
EXPIRED = 5;
// The sender cancelled this photo transfer.
CANCELLED = 6;
// The recipient owns this photo due to a rights transfer.
RECEIVED_VIA_TRANSFER = 7;
}
// Publication status of the photo in Google Maps.
enum MapsPublishStatus {
// The status of the photo is unknown.
UNSPECIFIED_MAPS_PUBLISH_STATUS = 0;
// The photo is published to the public through Google Maps.
PUBLISHED = 1;
// The photo has been rejected for an unknown reason.
REJECTED_UNKNOWN = 2;
}
// Required. Output only. Required when updating a photo. Output only when
// creating a photo. Identifier for the photo, which is unique among all
// photos in Google.
PhotoId photo_id = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.field_behavior) = OUTPUT_ONLY
];
// Input only. Required when creating a photo. Input only. The resource URL
// where the photo bytes are uploaded to.
UploadRef upload_reference = 2 [(google.api.field_behavior) = INPUT_ONLY];
// Output only. The download URL for the photo bytes. This field is set only
// when
// [GetPhotoRequest.view][google.streetview.publish.v1.GetPhotoRequest.view]
// is set to
// [PhotoView.INCLUDE_DOWNLOAD_URL][google.streetview.publish.v1.PhotoView.INCLUDE_DOWNLOAD_URL].
string download_url = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The thumbnail URL for showing a preview of the given photo.
string thumbnail_url = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The share link for the photo.
string share_link = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Pose of the photo.
Pose pose = 4 [(google.api.field_behavior) = OPTIONAL];
// Optional. Connections to other photos. A connection represents the link
// from this photo to another photo.
repeated Connection connections = 5 [(google.api.field_behavior) = OPTIONAL];
// Optional. Absolute time when the photo was captured.
// When the photo has no exif timestamp, this is used to set a timestamp in
// the photo metadata.
google.protobuf.Timestamp capture_time = 6
[(google.api.field_behavior) = OPTIONAL];
// Output only. Time when the image was uploaded.
google.protobuf.Timestamp upload_time = 14
[(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Places where this photo belongs.
repeated Place places = 7 [(google.api.field_behavior) = OPTIONAL];
// Output only. View count of the photo.
int64 view_count = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. Status of rights transfer on this photo.
TransferStatus transfer_status = 12
[(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. Status in Google Maps, whether this photo was published or
// rejected.
MapsPublishStatus maps_publish_status = 13
[(google.api.field_behavior) = OUTPUT_ONLY];
}
// A sequence of 360 photos along with metadata.
message PhotoSequence {
// Primary source of GPS measurements.
enum GpsSource {
// GPS in raw_gps_timeline takes precedence if it exists.
PHOTO_SEQUENCE = 0;
// GPS in Camera Motion Metadata Track (CAMM) takes precedence if it exists.
CAMERA_MOTION_METADATA_TRACK = 1;
}
// Output only. Unique identifier for the photo sequence.
// This also acts as a long running operation ID if uploading is performed
// asynchronously.
string id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. Photos with increasing timestamps.
repeated Photo photos = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// Input only. Required when creating photo sequence. The resource name
// where the bytes of the photo sequence (in the form of video) are uploaded.
UploadRef upload_reference = 3 [(google.api.field_behavior) = INPUT_ONLY];
// Optional. Absolute time when the photo sequence starts to be captured.
// If the photo sequence is a video, this is the start time of the video.
// If this field is populated in input, it overrides the capture time in the
// video or XDM file.
google.protobuf.Timestamp capture_time_override = 4
[(google.api.field_behavior) = OPTIONAL];
// Output only. The time this photo sequence was created in uSV Store service.
google.protobuf.Timestamp upload_time = 18
[(google.api.field_behavior) = OUTPUT_ONLY];
// Input only. Raw GPS measurements with increasing timestamps from the device
// that aren't time synced with each photo. These raw measurements will be
// used to infer the pose of each frame. Required in input when InputType is
// VIDEO and raw GPS measurements are not in Camera Motion Metadata Track
// (CAMM). User can indicate which takes precedence using gps_source if raw
// GPS measurements are provided in both raw_gps_timeline and Camera Motion
// Metadata Track (CAMM).
repeated Pose raw_gps_timeline = 7 [(google.api.field_behavior) = INPUT_ONLY];
// Input only. If both raw_gps_timeline and
// the Camera Motion Metadata Track (CAMM) contain GPS measurements,
// indicate which takes precedence.
GpsSource gps_source = 8 [(google.api.field_behavior) = INPUT_ONLY];
// Input only. Three axis IMU data for the collection.
// If this data is too large to put in the request, then it should be put in
// the CAMM track for the video. This data always takes precedence over the
// equivalent CAMM data, if it exists.
Imu imu = 11 [(google.api.field_behavior) = INPUT_ONLY];
// Output only. The processing state of this sequence.
ProcessingState processing_state = 12
[(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. If this sequence has processing_state = FAILED, this will
// contain the reason why it failed. If the processing_state is any other
// value, this field will be unset.
ProcessingFailureReason failure_reason = 13
[(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. If this sequence has `failure_reason` set, this may contain
// additional details about the failure.
ProcessingFailureDetails failure_details = 23
[(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The computed distance of the photo sequence in meters.
double distance_meters = 16 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. A rectangular box that encapsulates every image in this photo
// sequence.
LatLngBounds sequence_bounds = 20 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The total number of views that all the published images in
// this PhotoSequence have received.
int64 view_count = 21 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The filename of the upload. Does not include the directory
// path. Only available if the sequence was uploaded on a platform that
// provides the filename.
string filename = 22 [(google.api.field_behavior) = OUTPUT_ONLY];
}
// A rectangle in geographical coordinates.
message LatLngBounds {
// The southwest corner of these bounds.
google.type.LatLng southwest = 1;
// The northeast corner of these bounds.
google.type.LatLng northeast = 2;
}
// The processing state of the sequence. The states move as follows:
//
// ```
// +-------------------------+
// | |
// +---v---+ +----------+ +----+----+
// |PENDING+-->PROCESSING+-->PROCESSED|
// +---+---+ +----+-----+ +----+----+
// | | |
// | +--v---+ |
// +-------->FAILED<---------+
// +------+
// ```
//
// The sequence may move to FAILED from any state. Additionally, a processed
// sequence may be re-processed at any time.
enum ProcessingState {
// The state is unspecified, this is the default value.
PROCESSING_STATE_UNSPECIFIED = 0;
// The sequence has not yet started processing.
PENDING = 1;
// The sequence is currently in processing.
PROCESSING = 2;
// The sequence has finished processing including refining position.
PROCESSED = 3;
// The sequence failed processing. See FailureReason for more details.
FAILED = 4;
}
// The possible reasons this [PhotoSequence]
// [google.streetview.publish.v1.PhotoSequence] failed to process.
enum ProcessingFailureReason {
// The failure reason is unspecified, this is the default value.
PROCESSING_FAILURE_REASON_UNSPECIFIED = 0;
// Video frame's resolution is too small.
LOW_RESOLUTION = 1;
// This video has been uploaded before.
DUPLICATE = 2;
// Too few GPS points.
INSUFFICIENT_GPS = 3;
// No overlap between the time frame of GPS track and the time frame of
// video.
NO_OVERLAP_GPS = 4;
// GPS is invalid (e.x. all GPS points are at (0,0))
INVALID_GPS = 5;
// The sequence of photos could not be accurately located in the world.
FAILED_TO_REFINE_POSITIONS = 6;
// The sequence was taken down for policy reasons.
TAKEDOWN = 7;
// The video file was corrupt or could not be decoded.
CORRUPT_VIDEO = 8;
// A permanent failure in the underlying system occurred.
INTERNAL = 9;
// The video format is invalid or unsupported.
INVALID_VIDEO_FORMAT = 10;
// Invalid image aspect ratio found.
INVALID_VIDEO_DIMENSIONS = 11;
// Invalid capture time. Timestamps were from the future.
INVALID_CAPTURE_TIME = 12;
// GPS data contains a gap greater than 5 seconds in duration.
GPS_DATA_GAP = 13;
// GPS data is too erratic to be processed.
JUMPY_GPS = 14;
// IMU (Accelerometer, Gyroscope, etc.) data are not valid. They may be
// missing required fields (x, y, z or time), may not be formatted correctly,
// or any other issue that prevents our systems from parsing it.
INVALID_IMU = 15;
// Too few IMU points.
INSUFFICIENT_IMU = 21;
// Insufficient overlap in the time frame between GPS, IMU, and other time
// series data.
INSUFFICIENT_OVERLAP_TIME_SERIES = 22;
// IMU (Accelerometer, Gyroscope, etc.) data contain gaps greater than 0.1
// seconds in duration.
IMU_DATA_GAP = 16;
// The camera is not supported.
UNSUPPORTED_CAMERA = 17;
// Some frames were indoors, which is unsupported.
NOT_OUTDOORS = 18;
// Not enough video frames.
INSUFFICIENT_VIDEO_FRAMES = 19;
// Not enough moving data.
INSUFFICIENT_MOVEMENT = 20;
// Mast is down.
MAST_DOWN = 27;
// Camera is covered.
CAMERA_COVERED = 28;
}
// Additional details to accompany the ProcessingFailureReason enum.
// This message is always expected to be used in conjunction with
// ProcessingFailureReason, and the oneof value set in this message should match
// the FailureReason.
message ProcessingFailureDetails {
// Only one set of details will be set, and must match the corresponding enum
// in ProcessingFailureReason.
oneof details {
// See InsufficientGpsFailureDetails.
InsufficientGpsFailureDetails insufficient_gps_details = 1;
// See GpsDataGapFailureDetails.
GpsDataGapFailureDetails gps_data_gap_details = 2;
// See ImuDataGapFailureDetails.
ImuDataGapFailureDetails imu_data_gap_details = 3;
// See NotOutdoorsFailureDetails.
NotOutdoorsFailureDetails not_outdoors_details = 4;
// See NoOverlapGpsFailureDetails.
NoOverlapGpsFailureDetails no_overlap_gps_details = 5;
}
}
// Details related to ProcessingFailureReason#INSUFFICIENT_GPS.
message InsufficientGpsFailureDetails {
// The number of GPS points that were found in the video.
optional int32 gps_points_found = 1;
}
// Details related to ProcessingFailureReason#GPS_DATA_GAP.
// If there are multiple GPS data gaps, only the one with the largest duration
// is reported here.
message GpsDataGapFailureDetails {
// The duration of the gap in GPS data that was found.
optional google.protobuf.Duration gap_duration = 1;
// Relative time (from the start of the video stream) when the gap started.
optional google.protobuf.Duration gap_start_time = 2;
}
// Details related to ProcessingFailureReason#IMU_DATA_GAP.
// If there are multiple IMU data gaps, only the one with the largest duration
// is reported here.
message ImuDataGapFailureDetails {
// The duration of the gap in IMU data that was found.
optional google.protobuf.Duration gap_duration = 1;
// Relative time (from the start of the video stream) when the gap started.
optional google.protobuf.Duration gap_start_time = 2;
}
// Details related to ProcessingFailureReason#NOT_OUTDOORS.
// If there are multiple indoor frames found, the first frame is recorded here.
message NotOutdoorsFailureDetails {
// Relative time (from the start of the video stream) when an indoor frame was
// found.
optional google.protobuf.Duration start_time = 1;
}
// Details related to PhotoSequenceProcessingFailureReason#NO_OVERLAP_GPS.
message NoOverlapGpsFailureDetails {
// Time of first recorded GPS point.
optional google.protobuf.Timestamp gps_start_time = 1;
// Time of last recorded GPS point.
optional google.protobuf.Timestamp gps_end_time = 2;
// Start time of video.
optional google.protobuf.Timestamp video_start_time = 3;
// End time of video.
optional google.protobuf.Timestamp video_end_time = 4;
}