1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (C) 2010 David Conrad 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 22cabdff1aSopenharmony_ci#include "avformat.h" 23cabdff1aSopenharmony_ci#include "internal.h" 24cabdff1aSopenharmony_ci#include "oggdec.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_cistatic int skeleton_header(AVFormatContext *s, int idx) 27cabdff1aSopenharmony_ci{ 28cabdff1aSopenharmony_ci struct ogg *ogg = s->priv_data; 29cabdff1aSopenharmony_ci struct ogg_stream *os = ogg->streams + idx; 30cabdff1aSopenharmony_ci AVStream *st = s->streams[idx]; 31cabdff1aSopenharmony_ci uint8_t *buf = os->buf + os->pstart; 32cabdff1aSopenharmony_ci int version_major, version_minor; 33cabdff1aSopenharmony_ci int64_t start_num, start_den; 34cabdff1aSopenharmony_ci uint64_t start_granule; 35cabdff1aSopenharmony_ci int target_idx, start_time; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_DATA; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci if ((os->flags & OGG_FLAG_EOS) && os->psize == 0) 40cabdff1aSopenharmony_ci return 1; 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci if (os->psize < 8) 43cabdff1aSopenharmony_ci return -1; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci if (!strncmp(buf, "fishead", 8)) { 46cabdff1aSopenharmony_ci if (os->psize < 64) 47cabdff1aSopenharmony_ci return -1; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci version_major = AV_RL16(buf+8); 50cabdff1aSopenharmony_ci version_minor = AV_RL16(buf+10); 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci if (version_major != 3 && version_major != 4) { 53cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unknown skeleton version %d.%d\n", 54cabdff1aSopenharmony_ci version_major, version_minor); 55cabdff1aSopenharmony_ci return -1; 56cabdff1aSopenharmony_ci } 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci // This is the overall start time. We use it for the start time of 59cabdff1aSopenharmony_ci // of the skeleton stream since if left unset lavf assumes 0, 60cabdff1aSopenharmony_ci // which we don't want since skeleton is timeless 61cabdff1aSopenharmony_ci // FIXME: the real meaning of this field is "start playback at 62cabdff1aSopenharmony_ci // this time which can be in the middle of a packet 63cabdff1aSopenharmony_ci start_num = AV_RL64(buf+12); 64cabdff1aSopenharmony_ci start_den = AV_RL64(buf+20); 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci if (start_den > 0 && start_num > 0) { 67cabdff1aSopenharmony_ci int base_den; 68cabdff1aSopenharmony_ci av_reduce(&start_time, &base_den, start_num, start_den, INT_MAX); 69cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, base_den); 70cabdff1aSopenharmony_ci os->lastpts = 71cabdff1aSopenharmony_ci st->start_time = start_time; 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci } else if (!strncmp(buf, "fisbone", 8)) { 74cabdff1aSopenharmony_ci if (os->psize < 52) 75cabdff1aSopenharmony_ci return -1; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci target_idx = ogg_find_stream(ogg, AV_RL32(buf+12)); 78cabdff1aSopenharmony_ci start_granule = AV_RL64(buf+36); 79cabdff1aSopenharmony_ci if (target_idx < 0) { 80cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Serial number in fisbone doesn't match any stream\n"); 81cabdff1aSopenharmony_ci return 1; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci os = ogg->streams + target_idx; 84cabdff1aSopenharmony_ci if (os->start_granule != OGG_NOGRANULE_VALUE) { 85cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Multiple fisbone for the same stream\n"); 86cabdff1aSopenharmony_ci return 1; 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci if (start_granule != OGG_NOGRANULE_VALUE) { 89cabdff1aSopenharmony_ci os->start_granule = start_granule; 90cabdff1aSopenharmony_ci } 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci return 1; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ciconst struct ogg_codec ff_skeleton_codec = { 97cabdff1aSopenharmony_ci .magic = "fishead", 98cabdff1aSopenharmony_ci .magicsize = 8, 99cabdff1aSopenharmony_ci .header = skeleton_header, 100cabdff1aSopenharmony_ci .nb_header = 0, 101cabdff1aSopenharmony_ci}; 102