1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Raw FLAC demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2001 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 23cabdff1aSopenharmony_ci#include "libavcodec/flac.h" 24cabdff1aSopenharmony_ci#include "avformat.h" 25cabdff1aSopenharmony_ci#include "demux.h" 26cabdff1aSopenharmony_ci#include "flac_picture.h" 27cabdff1aSopenharmony_ci#include "internal.h" 28cabdff1aSopenharmony_ci#include "rawdec.h" 29cabdff1aSopenharmony_ci#include "oggdec.h" 30cabdff1aSopenharmony_ci#include "replaygain.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#define SEEKPOINT_SIZE 18 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct FLACDecContext { 35cabdff1aSopenharmony_ci FFRawDemuxerContext rawctx; 36cabdff1aSopenharmony_ci int found_seektable; 37cabdff1aSopenharmony_ci} FLACDecContext; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_cistatic void reset_index_position(int64_t metadata_head_size, AVStream *st) 40cabdff1aSopenharmony_ci{ 41cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 42cabdff1aSopenharmony_ci /* the real seek index offset should be the size of metadata blocks with the offset in the frame blocks */ 43cabdff1aSopenharmony_ci for (int i = 0; i < sti->nb_index_entries; i++) 44cabdff1aSopenharmony_ci sti->index_entries[i].pos += metadata_head_size; 45cabdff1aSopenharmony_ci} 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_cistatic int flac_read_header(AVFormatContext *s) 48cabdff1aSopenharmony_ci{ 49cabdff1aSopenharmony_ci int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0; 50cabdff1aSopenharmony_ci uint8_t header[4]; 51cabdff1aSopenharmony_ci uint8_t *buffer=NULL; 52cabdff1aSopenharmony_ci FLACDecContext *flac = s->priv_data; 53cabdff1aSopenharmony_ci AVStream *st = avformat_new_stream(s, NULL); 54cabdff1aSopenharmony_ci if (!st) 55cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 56cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 57cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_FLAC; 58cabdff1aSopenharmony_ci ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; 59cabdff1aSopenharmony_ci /* the parameters will be extracted from the compressed bitstream */ 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci /* if fLaC marker is not found, assume there is no header */ 62cabdff1aSopenharmony_ci if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) { 63cabdff1aSopenharmony_ci avio_seek(s->pb, -4, SEEK_CUR); 64cabdff1aSopenharmony_ci return 0; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci /* process metadata blocks */ 68cabdff1aSopenharmony_ci while (!avio_feof(s->pb) && !metadata_last) { 69cabdff1aSopenharmony_ci if (avio_read(s->pb, header, 4) != 4) 70cabdff1aSopenharmony_ci return AVERROR(AVERROR_INVALIDDATA); 71cabdff1aSopenharmony_ci flac_parse_block_header(header, &metadata_last, &metadata_type, 72cabdff1aSopenharmony_ci &metadata_size); 73cabdff1aSopenharmony_ci switch (metadata_type) { 74cabdff1aSopenharmony_ci /* allocate and read metadata block for supported types */ 75cabdff1aSopenharmony_ci case FLAC_METADATA_TYPE_STREAMINFO: 76cabdff1aSopenharmony_ci case FLAC_METADATA_TYPE_CUESHEET: 77cabdff1aSopenharmony_ci case FLAC_METADATA_TYPE_PICTURE: 78cabdff1aSopenharmony_ci case FLAC_METADATA_TYPE_VORBIS_COMMENT: 79cabdff1aSopenharmony_ci case FLAC_METADATA_TYPE_SEEKTABLE: 80cabdff1aSopenharmony_ci buffer = av_mallocz(metadata_size + AV_INPUT_BUFFER_PADDING_SIZE); 81cabdff1aSopenharmony_ci if (!buffer) { 82cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci if (avio_read(s->pb, buffer, metadata_size) != metadata_size) { 85cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR(EIO)); 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci break; 88cabdff1aSopenharmony_ci /* skip metadata block for unsupported types */ 89cabdff1aSopenharmony_ci default: 90cabdff1aSopenharmony_ci ret = avio_skip(s->pb, metadata_size); 91cabdff1aSopenharmony_ci if (ret < 0) 92cabdff1aSopenharmony_ci return ret; 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) { 96cabdff1aSopenharmony_ci uint32_t samplerate; 97cabdff1aSopenharmony_ci uint64_t samples; 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci /* STREAMINFO can only occur once */ 100cabdff1aSopenharmony_ci if (found_streaminfo) { 101cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci if (metadata_size != FLAC_STREAMINFO_SIZE) { 104cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 105cabdff1aSopenharmony_ci } 106cabdff1aSopenharmony_ci found_streaminfo = 1; 107cabdff1aSopenharmony_ci st->codecpar->extradata = buffer; 108cabdff1aSopenharmony_ci st->codecpar->extradata_size = metadata_size; 109cabdff1aSopenharmony_ci buffer = NULL; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci /* get sample rate and sample count from STREAMINFO header; 112cabdff1aSopenharmony_ci * other parameters will be extracted by the parser */ 113cabdff1aSopenharmony_ci samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4; 114cabdff1aSopenharmony_ci samples = (AV_RB64(st->codecpar->extradata + 13) >> 24) & ((1ULL << 36) - 1); 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci /* set time base and duration */ 117cabdff1aSopenharmony_ci if (samplerate > 0) { 118cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, samplerate); 119cabdff1aSopenharmony_ci if (samples > 0) 120cabdff1aSopenharmony_ci st->duration = samples; 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci } else if (metadata_type == FLAC_METADATA_TYPE_CUESHEET) { 123cabdff1aSopenharmony_ci uint8_t isrc[13]; 124cabdff1aSopenharmony_ci uint64_t start; 125cabdff1aSopenharmony_ci const uint8_t *offset; 126cabdff1aSopenharmony_ci int i, chapters, track, ti; 127cabdff1aSopenharmony_ci if (metadata_size < 431) 128cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 129cabdff1aSopenharmony_ci offset = buffer + 395; 130cabdff1aSopenharmony_ci chapters = bytestream_get_byte(&offset) - 1; 131cabdff1aSopenharmony_ci if (chapters <= 0) 132cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 133cabdff1aSopenharmony_ci for (i = 0; i < chapters; i++) { 134cabdff1aSopenharmony_ci if (offset + 36 - buffer > metadata_size) 135cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 136cabdff1aSopenharmony_ci start = bytestream_get_be64(&offset); 137cabdff1aSopenharmony_ci track = bytestream_get_byte(&offset); 138cabdff1aSopenharmony_ci bytestream_get_buffer(&offset, isrc, 12); 139cabdff1aSopenharmony_ci isrc[12] = 0; 140cabdff1aSopenharmony_ci offset += 14; 141cabdff1aSopenharmony_ci ti = bytestream_get_byte(&offset); 142cabdff1aSopenharmony_ci if (ti <= 0) RETURN_ERROR(AVERROR_INVALIDDATA); 143cabdff1aSopenharmony_ci offset += ti * 12; 144cabdff1aSopenharmony_ci avpriv_new_chapter(s, track, st->time_base, start, AV_NOPTS_VALUE, isrc); 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci av_freep(&buffer); 147cabdff1aSopenharmony_ci } else if (metadata_type == FLAC_METADATA_TYPE_PICTURE) { 148cabdff1aSopenharmony_ci ret = ff_flac_parse_picture(s, &buffer, metadata_size, 1); 149cabdff1aSopenharmony_ci av_freep(&buffer); 150cabdff1aSopenharmony_ci if (ret < 0) { 151cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Error parsing attached picture.\n"); 152cabdff1aSopenharmony_ci return ret; 153cabdff1aSopenharmony_ci } 154cabdff1aSopenharmony_ci } else if (metadata_type == FLAC_METADATA_TYPE_SEEKTABLE) { 155cabdff1aSopenharmony_ci const uint8_t *seekpoint = buffer; 156cabdff1aSopenharmony_ci int i, seek_point_count = metadata_size/SEEKPOINT_SIZE; 157cabdff1aSopenharmony_ci flac->found_seektable = 1; 158cabdff1aSopenharmony_ci if ((s->flags&AVFMT_FLAG_FAST_SEEK)) { 159cabdff1aSopenharmony_ci for(i=0; i<seek_point_count; i++) { 160cabdff1aSopenharmony_ci int64_t timestamp = bytestream_get_be64(&seekpoint); 161cabdff1aSopenharmony_ci int64_t pos = bytestream_get_be64(&seekpoint); 162cabdff1aSopenharmony_ci /* skip number of samples */ 163cabdff1aSopenharmony_ci bytestream_get_be16(&seekpoint); 164cabdff1aSopenharmony_ci av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME); 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci av_freep(&buffer); 168cabdff1aSopenharmony_ci } 169cabdff1aSopenharmony_ci else { 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci /* STREAMINFO must be the first block */ 172cabdff1aSopenharmony_ci if (!found_streaminfo) { 173cabdff1aSopenharmony_ci RETURN_ERROR(AVERROR_INVALIDDATA); 174cabdff1aSopenharmony_ci } 175cabdff1aSopenharmony_ci /* process supported blocks other than STREAMINFO */ 176cabdff1aSopenharmony_ci if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { 177cabdff1aSopenharmony_ci AVDictionaryEntry *chmask; 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci ret = ff_vorbis_comment(s, &s->metadata, buffer, metadata_size, 1); 180cabdff1aSopenharmony_ci if (ret < 0) { 181cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n"); 182cabdff1aSopenharmony_ci } else if (ret > 0) { 183cabdff1aSopenharmony_ci s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci /* parse the channels mask if present */ 187cabdff1aSopenharmony_ci chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); 188cabdff1aSopenharmony_ci if (chmask) { 189cabdff1aSopenharmony_ci uint64_t mask = strtol(chmask->value, NULL, 0); 190cabdff1aSopenharmony_ci if (!mask || mask & ~0x3ffffULL) { 191cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 192cabdff1aSopenharmony_ci "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); 193cabdff1aSopenharmony_ci } else { 194cabdff1aSopenharmony_ci av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); 195cabdff1aSopenharmony_ci av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci av_freep(&buffer); 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci } 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci ret = ff_replaygain_export(st, s->metadata); 204cabdff1aSopenharmony_ci if (ret < 0) 205cabdff1aSopenharmony_ci return ret; 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci reset_index_position(avio_tell(s->pb), st); 208cabdff1aSopenharmony_ci return 0; 209cabdff1aSopenharmony_ci 210cabdff1aSopenharmony_cifail: 211cabdff1aSopenharmony_ci av_free(buffer); 212cabdff1aSopenharmony_ci return ret; 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_cistatic int raw_flac_probe(const AVProbeData *p) 216cabdff1aSopenharmony_ci{ 217cabdff1aSopenharmony_ci if ((p->buf[2] & 0xF0) == 0) // blocksize code invalid 218cabdff1aSopenharmony_ci return 0; 219cabdff1aSopenharmony_ci if ((p->buf[2] & 0x0F) == 0x0F) // sample rate code invalid 220cabdff1aSopenharmony_ci return 0; 221cabdff1aSopenharmony_ci if ((p->buf[3] & 0xF0) >= FLAC_MAX_CHANNELS + FLAC_CHMODE_MID_SIDE << 4) 222cabdff1aSopenharmony_ci // channel mode invalid 223cabdff1aSopenharmony_ci return 0; 224cabdff1aSopenharmony_ci if ((p->buf[3] & 0x06) == 0x06) // bits per sample code invalid 225cabdff1aSopenharmony_ci return 0; 226cabdff1aSopenharmony_ci if ((p->buf[3] & 0x01) == 0x01) // reserved bit set 227cabdff1aSopenharmony_ci return 0; 228cabdff1aSopenharmony_ci return AVPROBE_SCORE_EXTENSION / 4 + 1; 229cabdff1aSopenharmony_ci} 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_cistatic int flac_probe(const AVProbeData *p) 232cabdff1aSopenharmony_ci{ 233cabdff1aSopenharmony_ci if ((AV_RB16(p->buf) & 0xFFFE) == 0xFFF8) 234cabdff1aSopenharmony_ci return raw_flac_probe(p); 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci /* file header + metadata header + checked bytes of streaminfo */ 237cabdff1aSopenharmony_ci if (p->buf_size >= 4 + 4 + 13) { 238cabdff1aSopenharmony_ci int type = p->buf[4] & 0x7f; 239cabdff1aSopenharmony_ci int size = AV_RB24(p->buf + 5); 240cabdff1aSopenharmony_ci int min_block_size = AV_RB16(p->buf + 8); 241cabdff1aSopenharmony_ci int max_block_size = AV_RB16(p->buf + 10); 242cabdff1aSopenharmony_ci int sample_rate = AV_RB24(p->buf + 18) >> 4; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci if (memcmp(p->buf, "fLaC", 4)) 245cabdff1aSopenharmony_ci return 0; 246cabdff1aSopenharmony_ci if (type == FLAC_METADATA_TYPE_STREAMINFO && 247cabdff1aSopenharmony_ci size == FLAC_STREAMINFO_SIZE && 248cabdff1aSopenharmony_ci min_block_size >= 16 && 249cabdff1aSopenharmony_ci max_block_size >= min_block_size && 250cabdff1aSopenharmony_ci sample_rate && sample_rate <= 655350) 251cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 252cabdff1aSopenharmony_ci return AVPROBE_SCORE_EXTENSION; 253cabdff1aSopenharmony_ci } 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci return 0; 256cabdff1aSopenharmony_ci} 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_cistatic av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_index, 259cabdff1aSopenharmony_ci int64_t *ppos, int64_t pos_limit) 260cabdff1aSopenharmony_ci{ 261cabdff1aSopenharmony_ci FFFormatContext *const si = ffformatcontext(s); 262cabdff1aSopenharmony_ci AVPacket *const pkt = si->parse_pkt; 263cabdff1aSopenharmony_ci AVStream *st = s->streams[stream_index]; 264cabdff1aSopenharmony_ci AVCodecParserContext *parser; 265cabdff1aSopenharmony_ci int ret; 266cabdff1aSopenharmony_ci int64_t pts = AV_NOPTS_VALUE; 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci if (avio_seek(s->pb, *ppos, SEEK_SET) < 0) 269cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci parser = av_parser_init(st->codecpar->codec_id); 272cabdff1aSopenharmony_ci if (!parser){ 273cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 274cabdff1aSopenharmony_ci } 275cabdff1aSopenharmony_ci parser->flags |= PARSER_FLAG_USE_CODEC_TS; 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci for (;;){ 278cabdff1aSopenharmony_ci uint8_t *data; 279cabdff1aSopenharmony_ci int size; 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci ret = ff_raw_read_partial_packet(s, pkt); 282cabdff1aSopenharmony_ci if (ret < 0){ 283cabdff1aSopenharmony_ci if (ret == AVERROR(EAGAIN)) 284cabdff1aSopenharmony_ci continue; 285cabdff1aSopenharmony_ci else { 286cabdff1aSopenharmony_ci av_packet_unref(pkt); 287cabdff1aSopenharmony_ci av_assert1(!pkt->size); 288cabdff1aSopenharmony_ci } 289cabdff1aSopenharmony_ci } 290cabdff1aSopenharmony_ci av_parser_parse2(parser, ffstream(st)->avctx, 291cabdff1aSopenharmony_ci &data, &size, pkt->data, pkt->size, 292cabdff1aSopenharmony_ci pkt->pts, pkt->dts, *ppos); 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci av_packet_unref(pkt); 295cabdff1aSopenharmony_ci if (size) { 296cabdff1aSopenharmony_ci if (parser->pts != AV_NOPTS_VALUE){ 297cabdff1aSopenharmony_ci // seeking may not have started from beginning of a frame 298cabdff1aSopenharmony_ci // calculate frame start position from next frame backwards 299cabdff1aSopenharmony_ci *ppos = parser->next_frame_offset - size; 300cabdff1aSopenharmony_ci pts = parser->pts; 301cabdff1aSopenharmony_ci break; 302cabdff1aSopenharmony_ci } 303cabdff1aSopenharmony_ci } else if (ret < 0) 304cabdff1aSopenharmony_ci break; 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci av_parser_close(parser); 307cabdff1aSopenharmony_ci return pts; 308cabdff1aSopenharmony_ci} 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_cistatic int flac_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { 311cabdff1aSopenharmony_ci AVStream *const st = s->streams[0]; 312cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 313cabdff1aSopenharmony_ci int index; 314cabdff1aSopenharmony_ci int64_t pos; 315cabdff1aSopenharmony_ci AVIndexEntry e; 316cabdff1aSopenharmony_ci FLACDecContext *flac = s->priv_data; 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci if (!flac->found_seektable || !(s->flags&AVFMT_FLAG_FAST_SEEK)) { 319cabdff1aSopenharmony_ci return -1; 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci index = av_index_search_timestamp(st, timestamp, flags); 323cabdff1aSopenharmony_ci if (index < 0 || index >= sti->nb_index_entries) 324cabdff1aSopenharmony_ci return -1; 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci e = sti->index_entries[index]; 327cabdff1aSopenharmony_ci pos = avio_seek(s->pb, e.pos, SEEK_SET); 328cabdff1aSopenharmony_ci if (pos >= 0) { 329cabdff1aSopenharmony_ci return 0; 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci return -1; 332cabdff1aSopenharmony_ci} 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ciconst AVInputFormat ff_flac_demuxer = { 335cabdff1aSopenharmony_ci .name = "flac", 336cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("raw FLAC"), 337cabdff1aSopenharmony_ci .read_probe = flac_probe, 338cabdff1aSopenharmony_ci .read_header = flac_read_header, 339cabdff1aSopenharmony_ci .read_packet = ff_raw_read_partial_packet, 340cabdff1aSopenharmony_ci .read_seek = flac_seek, 341cabdff1aSopenharmony_ci .read_timestamp = flac_read_timestamp, 342cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 343cabdff1aSopenharmony_ci .extensions = "flac", 344cabdff1aSopenharmony_ci .raw_codec_id = AV_CODEC_ID_FLAC, 345cabdff1aSopenharmony_ci .priv_data_size = sizeof(FLACDecContext), 346cabdff1aSopenharmony_ci .priv_class = &ff_raw_demuxer_class, 347cabdff1aSopenharmony_ci}; 348