1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2014 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/timeline.h"
41 uint32_t current_sample_description_index
;
45 static void remove_isobm_importer( isobm_importer_t
*isobm_imp
)
49 isobm_imp
->file
->bs
= NULL
; /* Don't destroy the bytestream handler here. */
50 lsmash_destroy_root( isobm_imp
->root
);
51 lsmash_free( isobm_imp
);
54 static isobm_importer_t
*create_isobm_importer( importer_t
*importer
)
56 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)lsmash_malloc_zero( sizeof(isobm_importer_t
) );
57 if( !(isobm_imp
->root
= lsmash_create_root()) )
59 if( !(isobm_imp
->file
= isom_add_file( isobm_imp
->root
)) )
61 isobm_imp
->root
->file
= isobm_imp
->file
;
62 isobm_imp
->file
->bs
= importer
->bs
;
63 isobm_imp
->file
->flags
|= LSMASH_FILE_MODE_READ
;
64 isobm_imp
->timebase
= 1;
67 remove_isobm_importer( isobm_imp
);
71 static void isobm_importer_cleanup( importer_t
*importer
)
73 debug_if( importer
&& importer
->info
)
74 remove_isobm_importer( importer
->info
);
77 static int isobm_importer_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
80 return LSMASH_ERR_NAMELESS
;
81 if( track_number
!= 1 )
82 return LSMASH_ERR_FUNCTION_PARAM
;
83 importer_status current_status
= importer
->status
;
84 if( current_status
== IMPORTER_ERROR
)
85 return LSMASH_ERR_NAMELESS
;
86 if( current_status
== IMPORTER_EOF
)
88 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)importer
->info
;
89 lsmash_root_t
*root
= isobm_imp
->root
;
90 uint32_t track_ID
= lsmash_get_track_ID( root
, track_number
);
91 if( track_ID
!= isobm_imp
->track_ID
)
92 return LSMASH_ERR_PATCH_WELCOME
;
93 lsmash_sample_t
*sample
= lsmash_get_sample_from_media_timeline( root
, track_ID
, isobm_imp
->au_number
+ 1 );
96 if( lsmash_check_sample_existence_in_media_timeline( root
, track_ID
, isobm_imp
->au_number
+ 1 ) )
97 return LSMASH_ERR_NAMELESS
;
100 /* No more samples. */
101 importer
->status
= IMPORTER_EOF
;
105 sample
->dts
/= isobm_imp
->timebase
;
106 sample
->cts
/= isobm_imp
->timebase
;
107 if( sample
->index
!= isobm_imp
->current_sample_description_index
)
109 /* Update the active summary. */
110 lsmash_summary_t
*summary
= lsmash_get_summary( isobm_imp
->root
, isobm_imp
->track_ID
, sample
->index
);
113 lsmash_delete_sample( sample
);
114 return LSMASH_ERR_NAMELESS
;
116 lsmash_remove_entry( importer
->summaries
, track_number
, lsmash_cleanup_summary
);
117 if( lsmash_add_entry( importer
->summaries
, summary
) < 0 )
119 lsmash_delete_sample( sample
);
120 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
121 return LSMASH_ERR_MEMORY_ALLOC
;
123 isobm_imp
->current_sample_description_index
= sample
->index
;
124 importer
->status
= IMPORTER_OK
;
125 current_status
= IMPORTER_CHANGE
;
128 ++ isobm_imp
->au_number
;
129 return current_status
;
132 static int isobm_importer_probe( importer_t
*importer
)
134 isobm_importer_t
*isobm_imp
= create_isobm_importer( importer
);
136 return LSMASH_ERR_MEMORY_ALLOC
;
138 if( (err
= lsmash_read_file( isobm_imp
->file
, NULL
)) < 0 )
140 if( !(isobm_imp
->file
->flags
& (LSMASH_FILE_MODE_BOX
141 | LSMASH_FILE_MODE_FRAGMENTED
142 | LSMASH_FILE_MODE_INITIALIZATION
143 | LSMASH_FILE_MODE_MEDIA
144 | LSMASH_FILE_MODE_INDEX
145 | LSMASH_FILE_MODE_SEGMENT
)) )
147 err
= LSMASH_ERR_INVALID_DATA
;
150 if( (isobm_imp
->track_ID
= lsmash_get_track_ID( isobm_imp
->root
, 1 )) == 0 )
152 err
= LSMASH_ERR_PATCH_WELCOME
;
155 if( (err
= lsmash_construct_timeline( isobm_imp
->root
, isobm_imp
->track_ID
)) < 0 )
157 lsmash_summary_t
*summary
= lsmash_get_summary( isobm_imp
->root
, isobm_imp
->track_ID
, 1 );
158 summary
->max_au_length
= lsmash_get_max_sample_size_in_media_timeline( isobm_imp
->root
, isobm_imp
->track_ID
);
159 if( summary
->summary_type
== LSMASH_SUMMARY_TYPE_VIDEO
)
161 lsmash_media_ts_list_t ts_list
;
162 if( (err
= lsmash_get_media_timestamps( isobm_imp
->root
, isobm_imp
->track_ID
, &ts_list
)) < 0 )
164 uint32_t last_sample_delta
;
165 if( (err
= lsmash_get_last_sample_delta_from_media_timeline( isobm_imp
->root
, isobm_imp
->track_ID
, &last_sample_delta
)) < 0 )
167 isobm_imp
->timebase
= last_sample_delta
;
168 for( uint32_t i
= 1; i
< ts_list
.sample_count
; i
++ )
169 isobm_imp
->timebase
= lsmash_get_gcd( isobm_imp
->timebase
, ts_list
.timestamp
[i
].dts
- ts_list
.timestamp
[i
- 1].dts
);
170 lsmash_sort_timestamps_composition_order( &ts_list
);
171 for( uint32_t i
= 1; i
< ts_list
.sample_count
; i
++ )
172 isobm_imp
->timebase
= lsmash_get_gcd( isobm_imp
->timebase
, ts_list
.timestamp
[i
].cts
- ts_list
.timestamp
[i
- 1].cts
);
173 lsmash_delete_media_timestamps( &ts_list
);
174 if( isobm_imp
->timebase
== 0 )
175 isobm_imp
->timebase
= 1;
176 ((lsmash_video_summary_t
*)summary
)->timebase
= isobm_imp
->timebase
;
177 ((lsmash_video_summary_t
*)summary
)->timescale
= lsmash_get_media_timescale( isobm_imp
->root
, isobm_imp
->track_ID
);
179 if( (err
= lsmash_add_entry( importer
->summaries
, summary
)) < 0 )
181 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
184 isobm_imp
->current_sample_description_index
= 1;
185 importer
->info
= isobm_imp
;
186 importer
->status
= IMPORTER_OK
;
189 remove_isobm_importer( isobm_imp
);
193 static uint32_t isobm_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
195 debug_if( !importer
|| !importer
->info
)
197 isobm_importer_t
*isobm_imp
= (isobm_importer_t
*)importer
->info
;
198 if( !isobm_imp
|| track_number
!= 1 )
200 uint32_t last_sample_delta
;
201 if( lsmash_get_last_sample_delta_from_media_timeline( isobm_imp
->root
, isobm_imp
->track_ID
, &last_sample_delta
) < 0 )
203 return last_sample_delta
/ isobm_imp
->timebase
;
206 const importer_functions isobm_importer
=
208 { "ISOBMFF/QTFF", offsetof( importer_t
, log_level
) },
210 isobm_importer_probe
,
211 isobm_importer_get_accessunit
,
212 isobm_importer_get_last_delta
,
213 isobm_importer_cleanup