9595]
9696
9797class Metadata (object ):
98- def __init__ (self ):
98+ def __init__ (self , projection = None , stereo_mode = None ):
99+ self .projection = None if (not projection or projection == "none" ) else projection
100+ self .stereo_mode = None if (not stereo_mode or stereo_mode == "none" ) else stereo_mode
99101 self .video = None
100102 self .audio = None
101103
@@ -152,7 +154,7 @@ def spherical_uuid(metadata):
152154 return uuid_leaf
153155
154156
155- def mpeg4_add_spherical (mpeg4_file , in_fh , metadata ):
157+ def mpeg4_add_spherical_xml_v1 (mpeg4_file , in_fh , metadata ):
156158 """Adds a spherical uuid box to an mpeg4 file for all video tracks.
157159
158160 Args:
@@ -184,6 +186,72 @@ def mpeg4_add_spherical(mpeg4_file, in_fh, metadata):
184186 mpeg4_file .resize ()
185187 return True
186188
189+ def mpeg4_add_spherical_v2 (mpeg4_file , in_fh , projection , stereo_mode ):
190+ for element in mpeg4_file .moov_box .contents :
191+ if element .name == mpeg .constants .TAG_TRAK :
192+ for sub_element in element .contents :
193+ if sub_element .name != mpeg .constants .TAG_MDIA :
194+ continue
195+ for mdia_sub_element in sub_element .contents :
196+ if mdia_sub_element .name != mpeg .constants .TAG_HDLR :
197+ continue
198+ position = mdia_sub_element .content_start () + 8
199+ in_fh .seek (position )
200+ if in_fh .read (4 ) == mpeg .constants .TAG_VIDE :
201+ ret = inject_spatial_video_v2_atoms (
202+ in_fh , sub_element , projection , stereo_mode )
203+ mpeg4_file .resize ()
204+ return ret
205+
206+
207+ def inject_spatial_video_v2_atoms (in_fh , video_media_atom , projection , stereo_mode ):
208+ """Adds spherical v2 boxes to an mpeg4 file for all video tracks.
209+
210+ Args:
211+ mpeg4_file: mpeg4, Mpeg4 file structure to add metadata.
212+ in_fh: file handle, Source for uncached file contents.
213+ metadata: string, xml metadata to inject into spherical tag.
214+ """
215+ for atom in video_media_atom .contents :
216+ if atom .name != mpeg .constants .TAG_MINF :
217+ continue
218+ for element in atom .contents :
219+ if element .name != mpeg .constants .TAG_STBL :
220+ continue
221+ for sub_element in element .contents :
222+ if sub_element .name != mpeg .constants .TAG_STSD :
223+ continue
224+ for sample_description in sub_element .contents :
225+ if sample_description .name in \
226+ mpeg .constants .VIDEO_SAMPLE_DESCRIPTIONS :
227+ in_fh .seek (sample_description .position +
228+ sample_description .header_size + 16 )
229+ # Should remove any existing boxes...
230+ if stereo_mode :
231+ st3d_atom = mpeg .sv3d .ST3DBox .create ()
232+ st3d_atom .name = mpeg .constants .TAG_ST3D
233+ st3d_atom .set_stereo_mode_from_string (stereo_mode )
234+
235+ sample_description .remove (st3d_atom .name )
236+ sample_description .add (st3d_atom )
237+
238+ if projection :
239+ proj_atom = mpeg .container .Container (header_size = 8 )
240+ proj_atom .name = mpeg .constants .TAG_PROJ
241+
242+ proj_atom .add (mpeg .sv3d .PRHDBox .create ())
243+ proj_atom .add (mpeg .sv3d .EQUIBox .create ())
244+
245+ sv3d_atom = mpeg .container .Container (header_size = 8 )
246+ sv3d_atom .name = mpeg .constants .TAG_SV3D
247+
248+ sv3d_atom .add (proj_atom )
249+
250+ sample_description .remove (sv3d_atom .name )
251+ sample_description .add (sv3d_atom )
252+
253+ return True
254+
187255
188256def mpeg4_add_spatial_audio (mpeg4_file , in_fh , audio_metadata , console ):
189257 """Adds spatial audio metadata to the first audio track of the input
@@ -355,6 +423,21 @@ def parse_spherical_mpeg4(mpeg4_file, fh, console):
355423 if sa3d_elem .name == mpeg .constants .TAG_SA3D :
356424 sa3d_elem .print_box (console )
357425 metadata .audio = sa3d_elem
426+
427+ for sv3d_container_elem in stsd_elem .contents :
428+ if sv3d_container_elem .name not in \
429+ mpeg .constants .VIDEO_SAMPLE_DESCRIPTIONS :
430+ continue
431+ for sub_elem in sv3d_container_elem .contents :
432+ if sub_elem .name == mpeg .constants .TAG_SV3D :
433+ console ("\t \t SV3D {" )
434+ sub_elem .print_box (console )
435+ console ("\t \t }" )
436+ elif sub_elem .name == mpeg .constants .TAG_ST3D :
437+ console ("\t \t ST3D {" )
438+ sub_elem .print_box (console )
439+ console ("\t \t } " )
440+
358441 return metadata
359442
360443def parse_mpeg4 (input_file , console ):
@@ -378,9 +461,13 @@ def inject_mpeg4(input_file, output_file, metadata, console):
378461 if mpeg4_file is None :
379462 console ("Error file could not be opened." )
380463
381- if not mpeg4_add_spherical (mpeg4_file , in_fh , metadata .video ):
464+ if metadata . video and not mpeg4_add_spherical_xml_v1 (mpeg4_file , in_fh , metadata .video ):
382465 console ("Error failed to insert spherical data" )
383466
467+ if ((metadata .projection or metadata .stereo_mode )
468+ and not mpeg4_add_spherical_v2 (mpeg4_file , in_fh , metadata .projection , metadata .stereo_mode )):
469+ console ("Error failed to insert spherical data v2" )
470+
384471 if metadata .audio :
385472 if not mpeg4_add_audio_metadata (
386473 mpeg4_file , in_fh , metadata .audio , console ):
0 commit comments