4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyuntae Kim <ht1211.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*=======================================================================================
24 =======================================================================================*/
27 #include <sys/vfs.h> /* struct statfs */
29 #include "mm_streamrecorder_internal.h"
30 #include "mm_streamrecorder_util.h"
31 #include "mm_streamrecorder_fileinfo.h"
33 /*-----------------------------------------------------------------------
34 | GLOBAL VARIABLE DEFINITIONS for internal |
35 -----------------------------------------------------------------------*/
37 /*-----------------------------------------------------------------------
38 | LOCAL VARIABLE DEFINITIONS for internal |
39 -----------------------------------------------------------------------*/
41 /*---------------------------------------------------------------------------
42 | LOCAL FUNCTION PROTOTYPES: |
43 ---------------------------------------------------------------------------*/
44 /* STATIC INTERNAL FUNCTION */
46 /*===========================================================================================
48 | FUNCTION DEFINITIONS |
49 ========================================================================================== */
50 /*---------------------------------------------------------------------------
51 | GLOBAL FUNCTION DEFINITIONS: |
52 ---------------------------------------------------------------------------*/
54 gboolean _mmstreamrecorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewind)
61 while (fread(&buf, sizeof(guchar), 8, f) > 0) {
62 unsigned long long buf_size = 0;
63 unsigned int buf_fourcc = MMSTREAMRECORDER_FOURCC(buf[4], buf[5], buf[6], buf[7]);
65 if (tag_fourcc == buf_fourcc) {
66 _mmstreamrec_dbg_log("find tag : %c%c%c%c", MMSTREAMRECORDER_FOURCC_ARGS(tag_fourcc));
68 } else if ((buf_fourcc == MMSTREAMRECORDER_FOURCC('m', 'o', 'o', 'v')) && (tag_fourcc != buf_fourcc)) {
69 if (_mmstreamrecorder_find_fourcc(f, tag_fourcc, FALSE))
74 _mmstreamrec_dbg_log("skip [%c%c%c%c] tag", MMSTREAMRECORDER_FOURCC_ARGS(buf_fourcc));
76 buf_size = (unsigned long long)_mmstreamrecorder_get_container_size(buf);
77 buf_size = buf_size - 8; /* include tag */
80 if (buf_size > _MMSTREAMRECORDER_MAX_INT) {
81 _mmstreamrec_dbg_log("seek %d", _MMSTREAMRECORDER_MAX_INT);
82 if (fseek(f, _MMSTREAMRECORDER_MAX_INT, SEEK_CUR) != 0) {
83 _mmstreamrec_dbg_err("fseek() fail");
87 buf_size -= _MMSTREAMRECORDER_MAX_INT;
89 _mmstreamrec_dbg_log("seek %d", buf_size);
90 if (fseek(f, buf_size, SEEK_CUR) != 0) {
91 _mmstreamrec_dbg_err("fseek() fail");
100 _mmstreamrec_dbg_log("cannot find tag : %c%c%c%c", MMSTREAMRECORDER_FOURCC_ARGS(tag_fourcc));
105 gboolean _mmstreamrecorder_update_composition_matrix(FILE *f, int orientation)
108 guint32 a = 0x00010000;
111 guint32 d = 0x00010000;
113 switch (orientation) {
114 case MM_STREAMRECORDER_TAG_VIDEO_ORT_90: /* 90 degree */
120 case MM_STREAMRECORDER_TAG_VIDEO_ORT_180: /* 180 degree */
124 case MM_STREAMRECORDER_TAG_VIDEO_ORT_270: /* 270 degree */
130 case MM_STREAMRECORDER_TAG_VIDEO_ORT_NONE: /* 0 degree */
143 write_to_32(f, 0x40000000);
145 _mmstreamrec_dbg_log("orientation : %d, write data 0x%x 0x%x 0x%x 0x%x", orientation, a, b, c, d);
150 guint64 _mmstreamrecorder_get_container_size(const guchar *size)
158 result = result | (temp << 16);
160 result = result | (temp << 8);
161 result = result | size[3];
163 _mmstreamrec_dbg_log("result : %lld", (unsigned long long)result);
168 gboolean _mmstreamrecorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos)
170 _mmstreamrec_dbg_log("size : %" G_GINT64_FORMAT "", curr_pos - prev_pos);
171 if (fseek(f, prev_pos, SEEK_SET) != 0) {
172 _mmstreamrec_dbg_err("fseek() fail");
176 if (!write_to_32(f, curr_pos - prev_pos))
179 if (fseek(f, curr_pos, SEEK_SET) != 0) {
180 _mmstreamrec_dbg_err("fseek() fail");
187 gboolean _mmstreamrecorder_write_udta_m4a(FILE *f)
189 gint64 current_pos, pos;
191 _mmstreamrec_dbg_log("");
193 if ((pos = ftell(f)) < 0) {
194 _mmstreamrec_dbg_err("ftell() returns negative value");
198 if (!write_to_32(f, 0)) /* udta atomic size */
201 if (!write_tag(f, "udta")) /* user data fourcc */
204 if ((current_pos = ftell(f)) < 0) {
205 _mmstreamrec_dbg_err("ftell() returns negative value");
209 if (!_mmstreamrecorder_update_size(f, pos, current_pos))
215 gboolean _mmstreamrecorder_write_udta(FILE *f, _MMStreamRecorderLocationInfo info)
217 gint64 current_pos, pos;
219 _mmstreamrec_dbg_log("");
221 if ((pos = ftell(f)) < 0) {
222 _mmstreamrec_dbg_err("ftell() returns negative value");
226 if (!write_to_32(f, 0)) /*size */
229 if (!write_tag(f, "udta")) /* type */
232 if ((current_pos = ftell(f)) < 0) {
233 _mmstreamrec_dbg_err("ftell() returns negative value");
237 if (!_mmstreamrecorder_update_size(f, pos, current_pos))
244 gboolean _mmstreamrecorder_audio_add_metadata_info_m4a(MMHandleType handle)
248 guint64 udta_size = 0;
249 gint64 current_pos = 0;
252 char err_msg[128] = { '\0', };
254 _MMStreamRecorderFileInfo *finfo = NULL;
255 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
256 _MMStreamRecorderSubContext *sc = NULL;
258 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
259 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
261 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
262 mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
264 finfo = sc->info_file;
266 f = fopen(finfo->filename, "rb+");
268 strerror_r(errno, err_msg, 128);
269 _mmstreamrec_dbg_err("file open failed [%s]", err_msg);
273 /* find udta container.
274 if, there are udta container, write loci box after that
275 else, make udta container and write loci box. */
276 if (_mmstreamrecorder_find_fourcc(f, MMSTREAMRECORDER_FOURCC('u', 'd', 't', 'a'), TRUE)) {
279 _mmstreamrec_dbg_log("find udta container");
282 if (fseek(f, -8L, SEEK_CUR) != 0)
289 nread = fread(&buf, sizeof(char), sizeof(buf), f);
291 _mmstreamrec_dbg_log("recorded file fread %d", nread);
293 udta_size = _mmstreamrecorder_get_container_size(buf);
295 /* goto end of udta and write 'smta' box */
296 if (fseek(f, (udta_size - 4L), SEEK_CUR) != 0)
299 current_pos = ftell(f);
303 if (!_mmstreamrecorder_update_size(f, udta_pos, current_pos))
306 _mmstreamrec_dbg_log("No udta container");
307 if (fseek(f, 0, SEEK_END) != 0)
310 if (!_mmstreamrecorder_write_udta_m4a(f))
314 /* find moov container.
315 update moov container size. */
316 if ((current_pos = ftell(f)) < 0)
319 if (_mmstreamrecorder_find_fourcc(f, MMSTREAMRECORDER_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
321 _mmstreamrec_dbg_log("found moov container");
322 if (fseek(f, -8L, SEEK_CUR) != 0)
329 if (!_mmstreamrecorder_update_size(f, moov_pos, current_pos))
333 _mmstreamrec_dbg_err("No 'moov' container");
345 _mmstreamrec_dbg_err("ftell() returns negative value.");