xref: /aosp_15_r20/external/googleapis/google/streetview/publish/v1/resources.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package google.streetview.publish.v1;
18
19import "google/api/field_behavior.proto";
20import "google/api/resource.proto";
21import "google/protobuf/duration.proto";
22import "google/protobuf/timestamp.proto";
23import "google/type/latlng.proto";
24
25option go_package = "google.golang.org/genproto/googleapis/streetview/publish/v1;publish";
26option java_outer_classname = "StreetViewPublishResources";
27option java_package = "com.google.geo.ugc.streetview.publish.v1";
28
29// Upload reference for media files.
30message UploadRef {
31  // Required.
32  oneof file_source {
33    // An upload reference should be unique for each user. It follows
34    // the form:
35    // "https://streetviewpublish.googleapis.com/media/user/{account_id}/photo/{upload_reference}"
36    string upload_url = 1;
37  }
38}
39
40// Identifier for a [Photo][google.streetview.publish.v1.Photo].
41message PhotoId {
42  // A unique identifier for a photo.
43  string id = 1;
44}
45
46// Level information containing level number and its corresponding name.
47message Level {
48  // Optional. Floor number, used for ordering. 0 indicates the ground level, 1
49  // indicates the first level above ground level, -1 indicates the first level
50  // under ground level. Non-integer values are OK.
51  double number = 1 [(google.api.field_behavior) = OPTIONAL];
52
53  // Required. A name assigned to this Level, restricted to 3 characters.
54  // Consider how the elevator buttons would be labeled for this level if there
55  // was an elevator.
56  string name = 2 [(google.api.field_behavior) = REQUIRED];
57}
58
59// Raw pose measurement for an entity.
60message Pose {
61  // Latitude and longitude pair of the pose, as explained here:
62  // https://cloud.google.com/datastore/docs/reference/rest/Shared.Types/LatLng
63  // When creating a [Photo][google.streetview.publish.v1.Photo], if the
64  // latitude and longitude pair are not provided, the geolocation from the
65  // exif header is used. A latitude and longitude pair not provided in the
66  // photo or exif header causes the photo process to fail.
67  google.type.LatLng lat_lng_pair = 1;
68
69  // Altitude of the pose in meters above WGS84 ellipsoid.
70  // NaN indicates an unmeasured quantity.
71  double altitude = 2;
72
73  // The following pose parameters pertain to the center of the photo. They
74  // match https://developers.google.com/streetview/spherical-metadata.
75  // Compass heading, measured at the center of the photo in degrees clockwise
76  // from North. Value must be >=0 and <360. NaN indicates an unmeasured
77  // quantity.
78  double heading = 3;
79
80  // Pitch, measured at the center of the photo in degrees. Value must be >=-90
81  // and <= 90. A value of -90 means looking directly down, and a value of 90
82  // means looking directly up.
83  // NaN indicates an unmeasured quantity.
84  double pitch = 4;
85
86  // Roll, measured in degrees. Value must be >= 0 and <360. A value of 0
87  // means level with the horizon.
88  // NaN indicates an unmeasured quantity.
89  double roll = 5;
90
91  // Time of the GPS record since UTC epoch.
92  google.protobuf.Timestamp gps_record_timestamp_unix_epoch = 6;
93
94  // Level (the floor in a building) used to configure vertical navigation.
95  Level level = 7;
96
97  // The estimated horizontal accuracy of this pose in meters with 68%
98  // confidence (one standard deviation). For example, on Android, this value is
99  // available from this method:
100  // https://developer.android.com/reference/android/location/Location#getAccuracy().
101  // Other platforms have different methods of obtaining similar accuracy
102  // estimations.
103  float accuracy_meters = 9;
104}
105
106// IMU data from the device sensors.
107message Imu {
108  // A Generic 3d measurement sample.
109  message Measurement3d {
110    // The timestamp of the IMU measurement.
111    google.protobuf.Timestamp capture_time = 1;
112
113    // The sensor measurement in the x axis.
114    float x = 2;
115
116    // The sensor measurement in the y axis.
117    float y = 3;
118
119    // The sensor measurement in the z axis.
120    float z = 4;
121  }
122
123  // The accelerometer measurements in meters/sec^2 with increasing timestamps
124  // from devices.
125  repeated Measurement3d accel_mpsps = 1;
126
127  // The gyroscope measurements in radians/sec with increasing timestamps from
128  // devices.
129  repeated Measurement3d gyro_rps = 2;
130
131  // The magnetometer measurements of the magnetic field in microtesla (uT) with
132  // increasing timestamps from devices.
133  repeated Measurement3d mag_ut = 3;
134}
135
136// Place metadata for an entity.
137message Place {
138  // Place identifier, as described in
139  // https://developers.google.com/places/place-id.
140  string place_id = 1;
141
142  // Output only. The name of the place, localized to the language_code.
143  string name = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
144
145  // Output only. The language_code that the name is localized with. This should
146  // be the language_code specified in the request, but may be a fallback.
147  string language_code = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
148}
149
150// A connection is the link from a source photo to a destination photo.
151message Connection {
152  // Required. The destination of the connection from the containing photo to
153  // another photo.
154  PhotoId target = 1 [(google.api.field_behavior) = REQUIRED];
155}
156
157// Photo is used to store 360 photos along with photo metadata.
158message Photo {
159  // Status of rights transfer.
160  enum TransferStatus {
161    // The status of this transfer is unspecified.
162    TRANSFER_STATUS_UNKNOWN = 0;
163
164    // This photo has never been in a transfer.
165    NEVER_TRANSFERRED = 1;
166
167    // This photo transfer has been initiated, but the receiver has not yet
168    // responded.
169    PENDING = 2;
170
171    // The photo transfer has been completed, and this photo has been
172    // transferred to the recipient.
173    COMPLETED = 3;
174
175    // The recipient rejected this photo transfer.
176    REJECTED = 4;
177
178    // The photo transfer expired before the recipient took any action.
179    EXPIRED = 5;
180
181    // The sender cancelled this photo transfer.
182    CANCELLED = 6;
183
184    // The recipient owns this photo due to a rights transfer.
185    RECEIVED_VIA_TRANSFER = 7;
186  }
187
188  // Publication status of the photo in Google Maps.
189  enum MapsPublishStatus {
190    // The status of the photo is unknown.
191    UNSPECIFIED_MAPS_PUBLISH_STATUS = 0;
192
193    // The photo is published to the public through Google Maps.
194    PUBLISHED = 1;
195
196    // The photo has been rejected for an unknown reason.
197    REJECTED_UNKNOWN = 2;
198  }
199
200  // Required. Output only. Required when updating a photo. Output only when
201  // creating a photo. Identifier for the photo, which is unique among all
202  // photos in Google.
203  PhotoId photo_id = 1 [
204    (google.api.field_behavior) = REQUIRED,
205    (google.api.field_behavior) = OUTPUT_ONLY
206  ];
207
208  // Input only. Required when creating a photo. Input only. The resource URL
209  // where the photo bytes are uploaded to.
210  UploadRef upload_reference = 2 [(google.api.field_behavior) = INPUT_ONLY];
211
212  // Output only. The download URL for the photo bytes. This field is set only
213  // when
214  // [GetPhotoRequest.view][google.streetview.publish.v1.GetPhotoRequest.view]
215  // is set to
216  // [PhotoView.INCLUDE_DOWNLOAD_URL][google.streetview.publish.v1.PhotoView.INCLUDE_DOWNLOAD_URL].
217  string download_url = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
218
219  // Output only. The thumbnail URL for showing a preview of the given photo.
220  string thumbnail_url = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
221
222  // Output only. The share link for the photo.
223  string share_link = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
224
225  // Optional. Pose of the photo.
226  Pose pose = 4 [(google.api.field_behavior) = OPTIONAL];
227
228  // Optional. Connections to other photos. A connection represents the link
229  // from this photo to another photo.
230  repeated Connection connections = 5 [(google.api.field_behavior) = OPTIONAL];
231
232  // Optional. Absolute time when the photo was captured.
233  // When the photo has no exif timestamp, this is used to set a timestamp in
234  // the photo metadata.
235  google.protobuf.Timestamp capture_time = 6
236      [(google.api.field_behavior) = OPTIONAL];
237
238  // Output only. Time when the image was uploaded.
239  google.protobuf.Timestamp upload_time = 14
240      [(google.api.field_behavior) = OUTPUT_ONLY];
241
242  // Optional. Places where this photo belongs.
243  repeated Place places = 7 [(google.api.field_behavior) = OPTIONAL];
244
245  // Output only. View count of the photo.
246  int64 view_count = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
247
248  // Output only. Status of rights transfer on this photo.
249  TransferStatus transfer_status = 12
250      [(google.api.field_behavior) = OUTPUT_ONLY];
251
252  // Output only. Status in Google Maps, whether this photo was published or
253  // rejected.
254  MapsPublishStatus maps_publish_status = 13
255      [(google.api.field_behavior) = OUTPUT_ONLY];
256}
257
258// A sequence of 360 photos along with metadata.
259message PhotoSequence {
260  // Primary source of GPS measurements.
261  enum GpsSource {
262    // GPS in raw_gps_timeline takes precedence if it exists.
263    PHOTO_SEQUENCE = 0;
264
265    // GPS in Camera Motion Metadata Track (CAMM) takes precedence if it exists.
266    CAMERA_MOTION_METADATA_TRACK = 1;
267  }
268
269  // Output only. Unique identifier for the photo sequence.
270  // This also acts as a long running operation ID if uploading is performed
271  // asynchronously.
272  string id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
273
274  // Output only. Photos with increasing timestamps.
275  repeated Photo photos = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
276
277  // Input only. Required when creating photo sequence. The resource name
278  // where the bytes of the photo sequence (in the form of video) are uploaded.
279  UploadRef upload_reference = 3 [(google.api.field_behavior) = INPUT_ONLY];
280
281  // Optional. Absolute time when the photo sequence starts to be captured.
282  // If the photo sequence is a video, this is the start time of the video.
283  // If this field is populated in input, it overrides the capture time in the
284  // video or XDM file.
285  google.protobuf.Timestamp capture_time_override = 4
286      [(google.api.field_behavior) = OPTIONAL];
287
288  // Output only. The time this photo sequence was created in uSV Store service.
289  google.protobuf.Timestamp upload_time = 18
290      [(google.api.field_behavior) = OUTPUT_ONLY];
291
292  // Input only. Raw GPS measurements with increasing timestamps from the device
293  // that aren't time synced with each photo. These raw measurements will be
294  // used to infer the pose of each frame. Required in input when InputType is
295  // VIDEO and raw GPS measurements are not in Camera Motion Metadata Track
296  // (CAMM). User can indicate which takes precedence using gps_source if raw
297  // GPS measurements are provided in both raw_gps_timeline and Camera Motion
298  // Metadata Track (CAMM).
299  repeated Pose raw_gps_timeline = 7 [(google.api.field_behavior) = INPUT_ONLY];
300
301  // Input only. If both raw_gps_timeline and
302  // the Camera Motion Metadata Track (CAMM) contain GPS measurements,
303  // indicate which takes precedence.
304  GpsSource gps_source = 8 [(google.api.field_behavior) = INPUT_ONLY];
305
306  // Input only. Three axis IMU data for the collection.
307  // If this data is too large to put in the request, then it should be put in
308  // the CAMM track for the video. This data always takes precedence over the
309  // equivalent CAMM data, if it exists.
310  Imu imu = 11 [(google.api.field_behavior) = INPUT_ONLY];
311
312  // Output only. The processing state of this sequence.
313  ProcessingState processing_state = 12
314      [(google.api.field_behavior) = OUTPUT_ONLY];
315
316  // Output only. If this sequence has processing_state = FAILED, this will
317  // contain the reason why it failed. If the processing_state is any other
318  // value, this field will be unset.
319  ProcessingFailureReason failure_reason = 13
320      [(google.api.field_behavior) = OUTPUT_ONLY];
321
322  // Output only. If this sequence has `failure_reason` set, this may contain
323  // additional details about the failure.
324  ProcessingFailureDetails failure_details = 23
325      [(google.api.field_behavior) = OUTPUT_ONLY];
326
327  // Output only. The computed distance of the photo sequence in meters.
328  double distance_meters = 16 [(google.api.field_behavior) = OUTPUT_ONLY];
329
330  // Output only. A rectangular box that encapsulates every image in this photo
331  // sequence.
332  LatLngBounds sequence_bounds = 20 [(google.api.field_behavior) = OUTPUT_ONLY];
333
334  // Output only. The total number of views that all the published images in
335  // this PhotoSequence have received.
336  int64 view_count = 21 [(google.api.field_behavior) = OUTPUT_ONLY];
337
338  // Output only. The filename of the upload. Does not include the directory
339  // path. Only available if the sequence was uploaded on a platform that
340  // provides the filename.
341  string filename = 22 [(google.api.field_behavior) = OUTPUT_ONLY];
342}
343
344// A rectangle in geographical coordinates.
345message LatLngBounds {
346  // The southwest corner of these bounds.
347  google.type.LatLng southwest = 1;
348
349  // The northeast corner of these bounds.
350  google.type.LatLng northeast = 2;
351}
352
353// The processing state of the sequence. The states move as follows:
354//
355// ```
356//      +-------------------------+
357//      |                         |
358//  +---v---+  +----------+  +----+----+
359//  |PENDING+-->PROCESSING+-->PROCESSED|
360//  +---+---+  +----+-----+  +----+----+
361//      |           |             |
362//      |        +--v---+         |
363//      +-------->FAILED<---------+
364//               +------+
365// ```
366//
367// The sequence may move to FAILED from any state. Additionally, a processed
368// sequence may be re-processed at any time.
369enum ProcessingState {
370  // The state is unspecified, this is the default value.
371  PROCESSING_STATE_UNSPECIFIED = 0;
372
373  // The sequence has not yet started processing.
374  PENDING = 1;
375
376  // The sequence is currently in processing.
377  PROCESSING = 2;
378
379  // The sequence has finished processing including refining position.
380  PROCESSED = 3;
381
382  // The sequence failed processing. See FailureReason for more details.
383  FAILED = 4;
384}
385
386// The possible reasons this [PhotoSequence]
387// [google.streetview.publish.v1.PhotoSequence] failed to process.
388enum ProcessingFailureReason {
389  // The failure reason is unspecified, this is the default value.
390  PROCESSING_FAILURE_REASON_UNSPECIFIED = 0;
391
392  // Video frame's resolution is too small.
393  LOW_RESOLUTION = 1;
394
395  // This video has been uploaded before.
396  DUPLICATE = 2;
397
398  // Too few GPS points.
399  INSUFFICIENT_GPS = 3;
400
401  // No overlap between the time frame of GPS track and the time frame of
402  // video.
403  NO_OVERLAP_GPS = 4;
404
405  // GPS is invalid (e.x. all GPS points are at (0,0))
406  INVALID_GPS = 5;
407
408  // The sequence of photos could not be accurately located in the world.
409  FAILED_TO_REFINE_POSITIONS = 6;
410
411  // The sequence was taken down for policy reasons.
412  TAKEDOWN = 7;
413
414  // The video file was corrupt or could not be decoded.
415  CORRUPT_VIDEO = 8;
416
417  // A permanent failure in the underlying system occurred.
418  INTERNAL = 9;
419
420  // The video format is invalid or unsupported.
421  INVALID_VIDEO_FORMAT = 10;
422
423  // Invalid image aspect ratio found.
424  INVALID_VIDEO_DIMENSIONS = 11;
425
426  // Invalid capture time. Timestamps were from the future.
427  INVALID_CAPTURE_TIME = 12;
428
429  // GPS data contains a gap greater than 5 seconds in duration.
430  GPS_DATA_GAP = 13;
431
432  // GPS data is too erratic to be processed.
433  JUMPY_GPS = 14;
434
435  // IMU (Accelerometer, Gyroscope, etc.) data are not valid. They may be
436  // missing required fields (x, y, z or time), may not be formatted correctly,
437  // or any other issue that prevents our systems from parsing it.
438  INVALID_IMU = 15;
439
440  // Too few IMU points.
441  INSUFFICIENT_IMU = 21;
442
443  // Insufficient overlap in the time frame between GPS, IMU, and other time
444  // series data.
445  INSUFFICIENT_OVERLAP_TIME_SERIES = 22;
446
447  // IMU (Accelerometer, Gyroscope, etc.) data contain gaps greater than 0.1
448  // seconds in duration.
449  IMU_DATA_GAP = 16;
450
451  // The camera is not supported.
452  UNSUPPORTED_CAMERA = 17;
453
454  // Some frames were indoors, which is unsupported.
455  NOT_OUTDOORS = 18;
456
457  // Not enough video frames.
458  INSUFFICIENT_VIDEO_FRAMES = 19;
459
460  // Not enough moving data.
461  INSUFFICIENT_MOVEMENT = 20;
462
463  // Mast is down.
464  MAST_DOWN = 27;
465
466  // Camera is covered.
467  CAMERA_COVERED = 28;
468}
469
470// Additional details to accompany the ProcessingFailureReason enum.
471// This message is always expected to be used in conjunction with
472// ProcessingFailureReason, and the oneof value set in this message should match
473// the FailureReason.
474message ProcessingFailureDetails {
475  // Only one set of details will be set, and must match the corresponding enum
476  // in ProcessingFailureReason.
477  oneof details {
478    // See InsufficientGpsFailureDetails.
479    InsufficientGpsFailureDetails insufficient_gps_details = 1;
480
481    // See GpsDataGapFailureDetails.
482    GpsDataGapFailureDetails gps_data_gap_details = 2;
483
484    // See ImuDataGapFailureDetails.
485    ImuDataGapFailureDetails imu_data_gap_details = 3;
486
487    // See NotOutdoorsFailureDetails.
488    NotOutdoorsFailureDetails not_outdoors_details = 4;
489
490    // See NoOverlapGpsFailureDetails.
491    NoOverlapGpsFailureDetails no_overlap_gps_details = 5;
492  }
493}
494
495// Details related to ProcessingFailureReason#INSUFFICIENT_GPS.
496message InsufficientGpsFailureDetails {
497  // The number of GPS points that were found in the video.
498  optional int32 gps_points_found = 1;
499}
500
501// Details related to ProcessingFailureReason#GPS_DATA_GAP.
502// If there are multiple GPS data gaps, only the one with the largest duration
503// is reported here.
504message GpsDataGapFailureDetails {
505  // The duration of the gap in GPS data that was found.
506  optional google.protobuf.Duration gap_duration = 1;
507
508  // Relative time (from the start of the video stream) when the gap started.
509  optional google.protobuf.Duration gap_start_time = 2;
510}
511
512// Details related to ProcessingFailureReason#IMU_DATA_GAP.
513// If there are multiple IMU data gaps, only the one with the largest duration
514// is reported here.
515message ImuDataGapFailureDetails {
516  // The duration of the gap in IMU data that was found.
517  optional google.protobuf.Duration gap_duration = 1;
518
519  // Relative time (from the start of the video stream) when the gap started.
520  optional google.protobuf.Duration gap_start_time = 2;
521}
522
523// Details related to ProcessingFailureReason#NOT_OUTDOORS.
524// If there are multiple indoor frames found, the first frame is recorded here.
525message NotOutdoorsFailureDetails {
526  // Relative time (from the start of the video stream) when an indoor frame was
527  // found.
528  optional google.protobuf.Duration start_time = 1;
529}
530
531// Details related to PhotoSequenceProcessingFailureReason#NO_OVERLAP_GPS.
532message NoOverlapGpsFailureDetails {
533  // Time of first recorded GPS point.
534  optional google.protobuf.Timestamp gps_start_time = 1;
535
536  // Time of last recorded GPS point.
537  optional google.protobuf.Timestamp gps_end_time = 2;
538
539  // Start time of video.
540  optional google.protobuf.Timestamp video_start_time = 3;
541
542  // End time of video.
543  optional google.protobuf.Timestamp video_end_time = 4;
544}
545