importer: Allocate sample buffer in individual importers.
[L-SMASH.git] / cli / isobm_imp.c
blob0fb1614897181960d8a7ba3b4e12e38498313d21
1 /*****************************************************************************
2 * isobm_imp.c
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 */
25 #include <string.h>
27 #define LSMASH_IMPORTER_INTERNAL
28 #include "importer.h"
30 /*********************************************************************************
31 ISO Base Media File Format (ISOBMFF) / QuickTime File Format (QTFF) importer
32 **********************************************************************************/
33 #include "core/timeline.h"
35 typedef struct
37 lsmash_root_t *root;
38 lsmash_file_t *file;
39 uint64_t timebase;
40 uint32_t track_ID;
41 uint32_t current_sample_description_index;
42 uint32_t au_number;
43 } isobm_importer_t;
45 static void remove_isobm_importer( isobm_importer_t *isobm_imp )
47 if( !isobm_imp )
48 return;
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()) )
58 goto fail;
59 if( !(isobm_imp->file = isom_add_file( isobm_imp->root )) )
60 goto fail;
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;
65 return isobm_imp;
66 fail:
67 remove_isobm_importer( isobm_imp );
68 return NULL;
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 )
79 if( !importer->info )
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 )
87 return 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 );
94 if( !sample )
96 if( lsmash_check_sample_existence_in_media_timeline( root, track_ID, isobm_imp->au_number + 1 ) )
97 return LSMASH_ERR_NAMELESS;
98 else
100 /* No more samples. */
101 importer->status = IMPORTER_EOF;
102 return 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 );
111 if( !summary )
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;
127 *p_sample = sample;
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 );
135 if( !isobm_imp )
136 return LSMASH_ERR_MEMORY_ALLOC;
137 int64_t err;
138 if( (err = lsmash_read_file( isobm_imp->file, NULL )) < 0 )
139 goto fail;
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;
148 goto fail;
150 if( (isobm_imp->track_ID = lsmash_get_track_ID( isobm_imp->root, 1 )) == 0 )
152 err = LSMASH_ERR_PATCH_WELCOME;
153 goto fail;
155 if( (err = lsmash_construct_timeline( isobm_imp->root, isobm_imp->track_ID )) < 0 )
156 goto fail;
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 )
163 goto fail;
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 )
166 goto fail;
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 );
182 goto fail;
184 isobm_imp->current_sample_description_index = 1;
185 importer->info = isobm_imp;
186 importer->status = IMPORTER_OK;
187 return 0;
188 fail:
189 remove_isobm_importer( isobm_imp );
190 return err;
193 static uint32_t isobm_importer_get_last_delta( importer_t *importer, uint32_t track_number )
195 debug_if( !importer || !importer->info )
196 return 0;
197 isobm_importer_t *isobm_imp = (isobm_importer_t *)importer->info;
198 if( !isobm_imp || track_number != 1 )
199 return 0;
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 )
202 return 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