1cabdff1aSopenharmony_ci/** 2cabdff1aSopenharmony_ci Copyright (C) 2005 Michael Ahlberg, Måns Rullgård 3cabdff1aSopenharmony_ci 4cabdff1aSopenharmony_ci Permission is hereby granted, free of charge, to any person 5cabdff1aSopenharmony_ci obtaining a copy of this software and associated documentation 6cabdff1aSopenharmony_ci files (the "Software"), to deal in the Software without 7cabdff1aSopenharmony_ci restriction, including without limitation the rights to use, copy, 8cabdff1aSopenharmony_ci modify, merge, publish, distribute, sublicense, and/or sell copies 9cabdff1aSopenharmony_ci of the Software, and to permit persons to whom the Software is 10cabdff1aSopenharmony_ci furnished to do so, subject to the following conditions: 11cabdff1aSopenharmony_ci 12cabdff1aSopenharmony_ci The above copyright notice and this permission notice shall be 13cabdff1aSopenharmony_ci included in all copies or substantial portions of the Software. 14cabdff1aSopenharmony_ci 15cabdff1aSopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16cabdff1aSopenharmony_ci EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17cabdff1aSopenharmony_ci MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18cabdff1aSopenharmony_ci NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19cabdff1aSopenharmony_ci HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20cabdff1aSopenharmony_ci WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21cabdff1aSopenharmony_ci OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22cabdff1aSopenharmony_ci DEALINGS IN THE SOFTWARE. 23cabdff1aSopenharmony_ci**/ 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include <stdlib.h> 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "avformat.h" 32cabdff1aSopenharmony_ci#include "internal.h" 33cabdff1aSopenharmony_ci#include "oggdec.h" 34cabdff1aSopenharmony_ci#include "riff.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_cistatic int 37cabdff1aSopenharmony_ciogm_header(AVFormatContext *s, int idx) 38cabdff1aSopenharmony_ci{ 39cabdff1aSopenharmony_ci struct ogg *ogg = s->priv_data; 40cabdff1aSopenharmony_ci struct ogg_stream *os = ogg->streams + idx; 41cabdff1aSopenharmony_ci AVStream *st = s->streams[idx]; 42cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 43cabdff1aSopenharmony_ci GetByteContext p; 44cabdff1aSopenharmony_ci uint64_t time_unit; 45cabdff1aSopenharmony_ci uint64_t spu; 46cabdff1aSopenharmony_ci uint32_t size; 47cabdff1aSopenharmony_ci int ret; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci bytestream2_init(&p, os->buf + os->pstart, os->psize); 50cabdff1aSopenharmony_ci if (!(bytestream2_peek_byte(&p) & 1)) 51cabdff1aSopenharmony_ci return 0; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci if (bytestream2_peek_byte(&p) == 1) { 54cabdff1aSopenharmony_ci bytestream2_skip(&p, 1); 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci if (bytestream2_peek_byte(&p) == 'v'){ 57cabdff1aSopenharmony_ci int tag; 58cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 59cabdff1aSopenharmony_ci bytestream2_skip(&p, 8); 60cabdff1aSopenharmony_ci tag = bytestream2_get_le32(&p); 61cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); 62cabdff1aSopenharmony_ci st->codecpar->codec_tag = tag; 63cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) 64cabdff1aSopenharmony_ci sti->need_parsing = AVSTREAM_PARSE_HEADERS; 65cabdff1aSopenharmony_ci } else if (bytestream2_peek_byte(&p) == 't') { 66cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; 67cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_TEXT; 68cabdff1aSopenharmony_ci bytestream2_skip(&p, 12); 69cabdff1aSopenharmony_ci } else { 70cabdff1aSopenharmony_ci uint8_t acid[5] = { 0 }; 71cabdff1aSopenharmony_ci int cid; 72cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 73cabdff1aSopenharmony_ci bytestream2_skip(&p, 8); 74cabdff1aSopenharmony_ci bytestream2_get_buffer(&p, acid, 4); 75cabdff1aSopenharmony_ci acid[4] = 0; 76cabdff1aSopenharmony_ci cid = strtol(acid, NULL, 16); 77cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid); 78cabdff1aSopenharmony_ci // our parser completely breaks AAC in Ogg 79cabdff1aSopenharmony_ci if (st->codecpar->codec_id != AV_CODEC_ID_AAC) 80cabdff1aSopenharmony_ci sti->need_parsing = AVSTREAM_PARSE_FULL; 81cabdff1aSopenharmony_ci } 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci size = bytestream2_get_le32(&p); 84cabdff1aSopenharmony_ci size = FFMIN(size, os->psize); 85cabdff1aSopenharmony_ci time_unit = bytestream2_get_le64(&p); 86cabdff1aSopenharmony_ci spu = bytestream2_get_le64(&p); 87cabdff1aSopenharmony_ci if (!time_unit || !spu) { 88cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Invalid timing values.\n"); 89cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 90cabdff1aSopenharmony_ci } 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci bytestream2_skip(&p, 4); /* default_len */ 93cabdff1aSopenharmony_ci bytestream2_skip(&p, 8); /* buffersize + bits_per_sample */ 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci if(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ 96cabdff1aSopenharmony_ci st->codecpar->width = bytestream2_get_le32(&p); 97cabdff1aSopenharmony_ci st->codecpar->height = bytestream2_get_le32(&p); 98cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, time_unit, spu * 10000000); 99cabdff1aSopenharmony_ci } else { 100cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = bytestream2_get_le16(&p); 101cabdff1aSopenharmony_ci bytestream2_skip(&p, 2); /* block_align */ 102cabdff1aSopenharmony_ci st->codecpar->bit_rate = bytestream2_get_le32(&p) * 8; 103cabdff1aSopenharmony_ci st->codecpar->sample_rate = spu * 10000000 / time_unit; 104cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 105cabdff1aSopenharmony_ci if (size >= 56 && st->codecpar->codec_id == AV_CODEC_ID_AAC) { 106cabdff1aSopenharmony_ci bytestream2_skip(&p, 4); 107cabdff1aSopenharmony_ci size -= 4; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci if (size > 52) { 110cabdff1aSopenharmony_ci size -= 52; 111cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&p) < size) 112cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 113cabdff1aSopenharmony_ci if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) 114cabdff1aSopenharmony_ci return ret; 115cabdff1aSopenharmony_ci bytestream2_get_buffer(&p, st->codecpar->extradata, st->codecpar->extradata_size); 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci } 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci // Update internal avctx with changes to codecpar above. 120cabdff1aSopenharmony_ci sti->need_context_update = 1; 121cabdff1aSopenharmony_ci } else if (bytestream2_peek_byte(&p) == 3) { 122cabdff1aSopenharmony_ci bytestream2_skip(&p, 7); 123cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&p) > 1) 124cabdff1aSopenharmony_ci ff_vorbis_stream_comment(s, st, p.buffer, bytestream2_get_bytes_left(&p) - 1); 125cabdff1aSopenharmony_ci } 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci return 1; 128cabdff1aSopenharmony_ci} 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_cistatic int 131cabdff1aSopenharmony_ciogm_dshow_header(AVFormatContext *s, int idx) 132cabdff1aSopenharmony_ci{ 133cabdff1aSopenharmony_ci struct ogg *ogg = s->priv_data; 134cabdff1aSopenharmony_ci struct ogg_stream *os = ogg->streams + idx; 135cabdff1aSopenharmony_ci AVStream *st = s->streams[idx]; 136cabdff1aSopenharmony_ci uint8_t *p = os->buf + os->pstart; 137cabdff1aSopenharmony_ci uint32_t t; 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci if(!(*p & 1)) 140cabdff1aSopenharmony_ci return 0; 141cabdff1aSopenharmony_ci if(*p != 1) 142cabdff1aSopenharmony_ci return 1; 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci if (os->psize < 100) 145cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 146cabdff1aSopenharmony_ci t = AV_RL32(p + 96); 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci if(t == 0x05589f80){ 149cabdff1aSopenharmony_ci if (os->psize < 184) 150cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 153cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68)); 154cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000); 155cabdff1aSopenharmony_ci st->codecpar->width = AV_RL32(p + 176); 156cabdff1aSopenharmony_ci st->codecpar->height = AV_RL32(p + 180); 157cabdff1aSopenharmony_ci } else if(t == 0x05589f81){ 158cabdff1aSopenharmony_ci if (os->psize < 136) 159cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 162cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124)); 163cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = AV_RL16(p + 126); 164cabdff1aSopenharmony_ci st->codecpar->sample_rate = AV_RL32(p + 128); 165cabdff1aSopenharmony_ci st->codecpar->bit_rate = AV_RL32(p + 132) * 8; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci return 1; 169cabdff1aSopenharmony_ci} 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_cistatic int 172cabdff1aSopenharmony_ciogm_packet(AVFormatContext *s, int idx) 173cabdff1aSopenharmony_ci{ 174cabdff1aSopenharmony_ci struct ogg *ogg = s->priv_data; 175cabdff1aSopenharmony_ci struct ogg_stream *os = ogg->streams + idx; 176cabdff1aSopenharmony_ci uint8_t *p = os->buf + os->pstart; 177cabdff1aSopenharmony_ci int lb; 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci if(*p & 8) 180cabdff1aSopenharmony_ci os->pflags |= AV_PKT_FLAG_KEY; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci lb = ((*p & 2) << 1) | ((*p >> 6) & 3); 183cabdff1aSopenharmony_ci if (os->psize < lb + 1) 184cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci os->pstart += lb + 1; 187cabdff1aSopenharmony_ci os->psize -= lb + 1; 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci while (lb--) 190cabdff1aSopenharmony_ci os->pduration += (uint64_t)p[lb+1] << (lb*8); 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci return 0; 193cabdff1aSopenharmony_ci} 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ciconst struct ogg_codec ff_ogm_video_codec = { 196cabdff1aSopenharmony_ci .magic = "\001video", 197cabdff1aSopenharmony_ci .magicsize = 6, 198cabdff1aSopenharmony_ci .header = ogm_header, 199cabdff1aSopenharmony_ci .packet = ogm_packet, 200cabdff1aSopenharmony_ci .granule_is_start = 1, 201cabdff1aSopenharmony_ci .nb_header = 2, 202cabdff1aSopenharmony_ci}; 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ciconst struct ogg_codec ff_ogm_audio_codec = { 205cabdff1aSopenharmony_ci .magic = "\001audio", 206cabdff1aSopenharmony_ci .magicsize = 6, 207cabdff1aSopenharmony_ci .header = ogm_header, 208cabdff1aSopenharmony_ci .packet = ogm_packet, 209cabdff1aSopenharmony_ci .granule_is_start = 1, 210cabdff1aSopenharmony_ci .nb_header = 2, 211cabdff1aSopenharmony_ci}; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ciconst struct ogg_codec ff_ogm_text_codec = { 214cabdff1aSopenharmony_ci .magic = "\001text", 215cabdff1aSopenharmony_ci .magicsize = 5, 216cabdff1aSopenharmony_ci .header = ogm_header, 217cabdff1aSopenharmony_ci .packet = ogm_packet, 218cabdff1aSopenharmony_ci .granule_is_start = 1, 219cabdff1aSopenharmony_ci .nb_header = 2, 220cabdff1aSopenharmony_ci}; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ciconst struct ogg_codec ff_ogm_old_codec = { 223cabdff1aSopenharmony_ci .magic = "\001Direct Show Samples embedded in Ogg", 224cabdff1aSopenharmony_ci .magicsize = 35, 225cabdff1aSopenharmony_ci .header = ogm_dshow_header, 226cabdff1aSopenharmony_ci .packet = ogm_packet, 227cabdff1aSopenharmony_ci .granule_is_start = 1, 228cabdff1aSopenharmony_ci .nb_header = 1, 229cabdff1aSopenharmony_ci}; 230