1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2014-2015 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
27 #define LSMASH_IMPORTER_INTERNAL
30 /*********************************************************************************
31 ISO Base Media File Format (ISOBMFF) / QuickTime File Format (QTFF) importer
32 **********************************************************************************/
33 #include "core/read.h"
34 #include "core/timeline.h"
40 uint32_t current_sample_description_index
;
44 static void remove_isobm_importer( isobm_importer_t
*isobm_imp
)
48 lsmash_free( isobm_imp
);
51 static isobm_importer_t
*create_isobm_importer( importer_t
*importer
)
53 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)lsmash_malloc_zero( sizeof(isobm_importer_t
) );
56 isobm_imp
->timebase
= 1;
63 static void isobm_importer_cleanup( importer_t
*importer
)
65 debug_if( importer
&& importer
->info
)
66 remove_isobm_importer( importer
->info
);
69 static int isobm_importer_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
72 return LSMASH_ERR_NAMELESS
;
73 if( track_number
!= 1 )
74 return LSMASH_ERR_FUNCTION_PARAM
;
75 importer_status current_status
= importer
->status
;
76 if( current_status
== IMPORTER_ERROR
)
77 return LSMASH_ERR_NAMELESS
;
78 if( current_status
== IMPORTER_EOF
)
80 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)importer
->info
;
81 lsmash_root_t
*root
= importer
->root
;
82 uint32_t track_ID
= lsmash_get_track_ID( root
, track_number
);
83 if( track_ID
!= isobm_imp
->track_ID
)
84 return LSMASH_ERR_PATCH_WELCOME
;
85 lsmash_sample_t
*sample
= lsmash_get_sample_from_media_timeline( root
, track_ID
, isobm_imp
->au_number
+ 1 );
88 if( lsmash_check_sample_existence_in_media_timeline( root
, track_ID
, isobm_imp
->au_number
+ 1 ) )
89 return LSMASH_ERR_NAMELESS
;
92 /* No more samples. */
93 importer
->status
= IMPORTER_EOF
;
97 sample
->dts
/= isobm_imp
->timebase
;
98 sample
->cts
/= isobm_imp
->timebase
;
99 if( sample
->index
!= isobm_imp
->current_sample_description_index
)
101 /* Update the active summary. */
102 lsmash_summary_t
*summary
= lsmash_get_summary( root
, track_ID
, sample
->index
);
105 lsmash_delete_sample( sample
);
106 return LSMASH_ERR_NAMELESS
;
108 lsmash_remove_entry( importer
->summaries
, track_number
, lsmash_cleanup_summary
);
109 if( lsmash_add_entry( importer
->summaries
, summary
) < 0 )
111 lsmash_delete_sample( sample
);
112 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
113 return LSMASH_ERR_MEMORY_ALLOC
;
115 isobm_imp
->current_sample_description_index
= sample
->index
;
116 importer
->status
= IMPORTER_OK
;
117 current_status
= IMPORTER_CHANGE
;
120 ++ isobm_imp
->au_number
;
121 return current_status
;
124 static int isobm_importer_probe( importer_t
*importer
)
126 isobm_importer_t
*isobm_imp
= create_isobm_importer( importer
);
128 return LSMASH_ERR_MEMORY_ALLOC
;
130 /* Get the file size if seekable when reading. */
131 lsmash_bs_t
*bs
= importer
->bs
;
132 if( !bs
->unseekable
)
134 int64_t ret
= lsmash_bs_read_seek( bs
, 0, SEEK_END
);
141 lsmash_bs_read_seek( bs
, 0, SEEK_SET
);
143 if( (err
= isom_read_file( importer
->file
)) < 0 )
145 if( !(importer
->file
->flags
& (LSMASH_FILE_MODE_BOX
146 | LSMASH_FILE_MODE_FRAGMENTED
147 | LSMASH_FILE_MODE_INITIALIZATION
148 | LSMASH_FILE_MODE_MEDIA
149 | LSMASH_FILE_MODE_INDEX
150 | LSMASH_FILE_MODE_SEGMENT
)) )
152 err
= LSMASH_ERR_INVALID_DATA
;
155 importer
->file
->flags
|= LSMASH_FILE_MODE_BOX
;
156 lsmash_root_t
*root
= importer
->root
;
157 if( root
&& root
== importer
->file
->root
)
159 if( (isobm_imp
->track_ID
= lsmash_get_track_ID( root
, 1 )) == 0 )
161 err
= LSMASH_ERR_PATCH_WELCOME
;
164 lsmash_summary_t
*summary
= lsmash_get_summary( root
, isobm_imp
->track_ID
, 1 );
165 if( (err
= lsmash_add_entry( importer
->summaries
, summary
)) < 0 )
167 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
170 isobm_imp
->current_sample_description_index
= 1;
172 importer
->info
= isobm_imp
;
173 importer
->status
= IMPORTER_OK
;
176 remove_isobm_importer( isobm_imp
);
180 static uint32_t isobm_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
182 debug_if( !importer
|| !importer
->info
)
184 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)importer
->info
;
185 if( !isobm_imp
|| track_number
!= 1 )
187 uint32_t last_sample_delta
;
188 if( lsmash_get_last_sample_delta_from_media_timeline( importer
->root
, isobm_imp
->track_ID
, &last_sample_delta
) < 0 )
190 return last_sample_delta
/ isobm_imp
->timebase
;
193 static int isobm_importer_construct_timeline( importer_t
*importer
, uint32_t track_number
)
195 lsmash_root_t
*root
= importer
->root
;
196 uint32_t track_ID
= lsmash_get_track_ID( root
, track_number
);
197 int err
= isom_timeline_construct( root
, track_ID
);
200 if( root
&& root
== importer
->file
->root
)
202 lsmash_summary_t
*summary
= lsmash_get_entry_data( importer
->summaries
, track_number
);
204 return LSMASH_ERR_NAMELESS
;
205 summary
->max_au_length
= lsmash_get_max_sample_size_in_media_timeline( root
, track_ID
);
206 if( summary
->summary_type
== LSMASH_SUMMARY_TYPE_VIDEO
)
208 lsmash_media_ts_list_t ts_list
;
209 if( (err
= lsmash_get_media_timestamps( root
, track_ID
, &ts_list
)) < 0 )
211 uint32_t last_sample_delta
;
212 if( (err
= lsmash_get_last_sample_delta_from_media_timeline( root
, track_ID
, &last_sample_delta
)) < 0 )
214 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)importer
->info
;
215 isobm_imp
->timebase
= last_sample_delta
;
216 for( uint32_t i
= 1; i
< ts_list
.sample_count
; i
++ )
217 isobm_imp
->timebase
= lsmash_get_gcd( isobm_imp
->timebase
, ts_list
.timestamp
[i
].dts
- ts_list
.timestamp
[i
- 1].dts
);
218 lsmash_sort_timestamps_composition_order( &ts_list
);
219 for( uint32_t i
= 1; i
< ts_list
.sample_count
; i
++ )
220 isobm_imp
->timebase
= lsmash_get_gcd( isobm_imp
->timebase
, ts_list
.timestamp
[i
].cts
- ts_list
.timestamp
[i
- 1].cts
);
221 lsmash_delete_media_timestamps( &ts_list
);
222 if( isobm_imp
->timebase
== 0 )
223 isobm_imp
->timebase
= 1;
224 ((lsmash_video_summary_t
*)summary
)->timebase
= isobm_imp
->timebase
;
225 ((lsmash_video_summary_t
*)summary
)->timescale
= lsmash_get_media_timescale( root
, track_ID
);
231 const importer_functions isobm_importer
=
233 { "ISOBMFF/QTFF", offsetof( importer_t
, log_level
) },
235 isobm_importer_probe
,
236 isobm_importer_get_accessunit
,
237 isobm_importer_get_last_delta
,
238 isobm_importer_cleanup
,
239 isobm_importer_construct_timeline