1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Digital Speech Standard (DSS) demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2014 Oleksij Rempel <linux@rempel-privat.de> 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 "libavutil/intreadwrite.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "avformat.h" 26cabdff1aSopenharmony_ci#include "internal.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#define DSS_HEAD_OFFSET_AUTHOR 0xc 29cabdff1aSopenharmony_ci#define DSS_AUTHOR_SIZE 16 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#define DSS_HEAD_OFFSET_START_TIME 0x26 32cabdff1aSopenharmony_ci#define DSS_HEAD_OFFSET_END_TIME 0x32 33cabdff1aSopenharmony_ci#define DSS_TIME_SIZE 12 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#define DSS_HEAD_OFFSET_ACODEC 0x2a4 36cabdff1aSopenharmony_ci#define DSS_ACODEC_DSS_SP 0x0 /* SP mode */ 37cabdff1aSopenharmony_ci#define DSS_ACODEC_G723_1 0x2 /* LP mode */ 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci#define DSS_HEAD_OFFSET_COMMENT 0x31e 40cabdff1aSopenharmony_ci#define DSS_COMMENT_SIZE 64 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#define DSS_BLOCK_SIZE 512 43cabdff1aSopenharmony_ci#define DSS_AUDIO_BLOCK_HEADER_SIZE 6 44cabdff1aSopenharmony_ci#define DSS_FRAME_SIZE 42 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic const uint8_t frame_size[4] = { 24, 20, 4, 1 }; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_citypedef struct DSSDemuxContext { 49cabdff1aSopenharmony_ci unsigned int audio_codec; 50cabdff1aSopenharmony_ci int counter; 51cabdff1aSopenharmony_ci int swap; 52cabdff1aSopenharmony_ci int dss_sp_swap_byte; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci int packet_size; 55cabdff1aSopenharmony_ci int dss_header_size; 56cabdff1aSopenharmony_ci} DSSDemuxContext; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_cistatic int dss_probe(const AVProbeData *p) 59cabdff1aSopenharmony_ci{ 60cabdff1aSopenharmony_ci if ( AV_RL32(p->buf) != MKTAG(0x2, 'd', 's', 's') 61cabdff1aSopenharmony_ci && AV_RL32(p->buf) != MKTAG(0x3, 'd', 's', 's')) 62cabdff1aSopenharmony_ci return 0; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 65cabdff1aSopenharmony_ci} 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic int dss_read_metadata_date(AVFormatContext *s, unsigned int offset, 68cabdff1aSopenharmony_ci const char *key) 69cabdff1aSopenharmony_ci{ 70cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 71cabdff1aSopenharmony_ci char datetime[64], string[DSS_TIME_SIZE + 1] = { 0 }; 72cabdff1aSopenharmony_ci int y, month, d, h, minute, sec; 73cabdff1aSopenharmony_ci int ret; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci avio_seek(pb, offset, SEEK_SET); 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci ret = avio_read(s->pb, string, DSS_TIME_SIZE); 78cabdff1aSopenharmony_ci if (ret < DSS_TIME_SIZE) 79cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR_EOF; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci if (sscanf(string, "%2d%2d%2d%2d%2d%2d", &y, &month, &d, &h, &minute, &sec) != 6) 82cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 83cabdff1aSopenharmony_ci /* We deal with a two-digit year here, so set the default date to 2000 84cabdff1aSopenharmony_ci * and hope it will never be used in the next century. */ 85cabdff1aSopenharmony_ci snprintf(datetime, sizeof(datetime), "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", 86cabdff1aSopenharmony_ci y + 2000, month, d, h, minute, sec); 87cabdff1aSopenharmony_ci return av_dict_set(&s->metadata, key, datetime, 0); 88cabdff1aSopenharmony_ci} 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_cistatic int dss_read_metadata_string(AVFormatContext *s, unsigned int offset, 91cabdff1aSopenharmony_ci unsigned int size, const char *key) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 94cabdff1aSopenharmony_ci char *value; 95cabdff1aSopenharmony_ci int ret; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci avio_seek(pb, offset, SEEK_SET); 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci value = av_mallocz(size + 1); 100cabdff1aSopenharmony_ci if (!value) 101cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci ret = avio_read(s->pb, value, size); 104cabdff1aSopenharmony_ci if (ret < size) { 105cabdff1aSopenharmony_ci av_free(value); 106cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR_EOF; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci return av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); 110cabdff1aSopenharmony_ci} 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_cistatic int dss_read_header(AVFormatContext *s) 113cabdff1aSopenharmony_ci{ 114cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 115cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 116cabdff1aSopenharmony_ci AVStream *st; 117cabdff1aSopenharmony_ci int ret, version; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 120cabdff1aSopenharmony_ci if (!st) 121cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci version = avio_r8(pb); 124cabdff1aSopenharmony_ci ctx->dss_header_size = version * DSS_BLOCK_SIZE; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_AUTHOR, 127cabdff1aSopenharmony_ci DSS_AUTHOR_SIZE, "author"); 128cabdff1aSopenharmony_ci if (ret) 129cabdff1aSopenharmony_ci return ret; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci ret = dss_read_metadata_date(s, DSS_HEAD_OFFSET_END_TIME, "date"); 132cabdff1aSopenharmony_ci if (ret) 133cabdff1aSopenharmony_ci return ret; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_COMMENT, 136cabdff1aSopenharmony_ci DSS_COMMENT_SIZE, "comment"); 137cabdff1aSopenharmony_ci if (ret) 138cabdff1aSopenharmony_ci return ret; 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci avio_seek(pb, DSS_HEAD_OFFSET_ACODEC, SEEK_SET); 141cabdff1aSopenharmony_ci ctx->audio_codec = avio_r8(pb); 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci if (ctx->audio_codec == DSS_ACODEC_DSS_SP) { 144cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_DSS_SP; 145cabdff1aSopenharmony_ci st->codecpar->sample_rate = 11025; 146cabdff1aSopenharmony_ci s->bit_rate = 8 * (DSS_FRAME_SIZE - 1) * st->codecpar->sample_rate 147cabdff1aSopenharmony_ci * 512 / (506 * 264); 148cabdff1aSopenharmony_ci } else if (ctx->audio_codec == DSS_ACODEC_G723_1) { 149cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_G723_1; 150cabdff1aSopenharmony_ci st->codecpar->sample_rate = 8000; 151cabdff1aSopenharmony_ci } else { 152cabdff1aSopenharmony_ci avpriv_request_sample(s, "Support for codec %x in DSS", 153cabdff1aSopenharmony_ci ctx->audio_codec); 154cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 158cabdff1aSopenharmony_ci st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 161cabdff1aSopenharmony_ci st->start_time = 0; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci /* Jump over header */ 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci if (avio_seek(pb, ctx->dss_header_size, SEEK_SET) != ctx->dss_header_size) 166cabdff1aSopenharmony_ci return AVERROR(EIO); 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci ctx->counter = 0; 169cabdff1aSopenharmony_ci ctx->swap = 0; 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci return 0; 172cabdff1aSopenharmony_ci} 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_cistatic void dss_skip_audio_header(AVFormatContext *s, AVPacket *pkt) 175cabdff1aSopenharmony_ci{ 176cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 177cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci avio_skip(pb, DSS_AUDIO_BLOCK_HEADER_SIZE); 180cabdff1aSopenharmony_ci ctx->counter += DSS_BLOCK_SIZE - DSS_AUDIO_BLOCK_HEADER_SIZE; 181cabdff1aSopenharmony_ci} 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_cistatic void dss_sp_byte_swap(DSSDemuxContext *ctx, uint8_t *data) 184cabdff1aSopenharmony_ci{ 185cabdff1aSopenharmony_ci int i; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci if (ctx->swap) { 188cabdff1aSopenharmony_ci for (i = 0; i < DSS_FRAME_SIZE - 2; i += 2) 189cabdff1aSopenharmony_ci data[i] = data[i + 4]; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci /* Zero the padding. */ 192cabdff1aSopenharmony_ci data[DSS_FRAME_SIZE] = 0; 193cabdff1aSopenharmony_ci data[1] = ctx->dss_sp_swap_byte; 194cabdff1aSopenharmony_ci } else { 195cabdff1aSopenharmony_ci ctx->dss_sp_swap_byte = data[DSS_FRAME_SIZE - 2]; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci /* make sure byte 40 is always 0 */ 199cabdff1aSopenharmony_ci data[DSS_FRAME_SIZE - 2] = 0; 200cabdff1aSopenharmony_ci ctx->swap ^= 1; 201cabdff1aSopenharmony_ci} 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_cistatic int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt) 204cabdff1aSopenharmony_ci{ 205cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 206cabdff1aSopenharmony_ci int read_size, ret, offset = 0, buff_offset = 0; 207cabdff1aSopenharmony_ci int64_t pos = avio_tell(s->pb); 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci if (ctx->counter == 0) 210cabdff1aSopenharmony_ci dss_skip_audio_header(s, pkt); 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (ctx->swap) { 213cabdff1aSopenharmony_ci read_size = DSS_FRAME_SIZE - 2; 214cabdff1aSopenharmony_ci buff_offset = 3; 215cabdff1aSopenharmony_ci } else 216cabdff1aSopenharmony_ci read_size = DSS_FRAME_SIZE; 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci ret = av_new_packet(pkt, DSS_FRAME_SIZE); 219cabdff1aSopenharmony_ci if (ret < 0) 220cabdff1aSopenharmony_ci return ret; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci pkt->duration = 264; 223cabdff1aSopenharmony_ci pkt->pos = pos; 224cabdff1aSopenharmony_ci pkt->stream_index = 0; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci if (ctx->counter < read_size) { 227cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + buff_offset, 228cabdff1aSopenharmony_ci ctx->counter); 229cabdff1aSopenharmony_ci if (ret < ctx->counter) 230cabdff1aSopenharmony_ci goto error_eof; 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci offset = ctx->counter; 233cabdff1aSopenharmony_ci dss_skip_audio_header(s, pkt); 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci ctx->counter -= read_size; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci /* This will write one byte into pkt's padding if buff_offset == 3 */ 238cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + offset + buff_offset, 239cabdff1aSopenharmony_ci read_size - offset); 240cabdff1aSopenharmony_ci if (ret < read_size - offset) 241cabdff1aSopenharmony_ci goto error_eof; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci dss_sp_byte_swap(ctx, pkt->data); 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci if (ctx->dss_sp_swap_byte < 0) { 246cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 247cabdff1aSopenharmony_ci } 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_ci return 0; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_cierror_eof: 252cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR_EOF; 253cabdff1aSopenharmony_ci} 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_cistatic int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt) 256cabdff1aSopenharmony_ci{ 257cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 258cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 259cabdff1aSopenharmony_ci int size, byte, ret, offset; 260cabdff1aSopenharmony_ci int64_t pos = avio_tell(s->pb); 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci if (ctx->counter == 0) 263cabdff1aSopenharmony_ci dss_skip_audio_header(s, pkt); 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci /* We make one byte-step here. Don't forget to add offset. */ 266cabdff1aSopenharmony_ci byte = avio_r8(s->pb); 267cabdff1aSopenharmony_ci if (byte == 0xff) 268cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci size = frame_size[byte & 3]; 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci ctx->packet_size = size; 273cabdff1aSopenharmony_ci ctx->counter--; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci ret = av_new_packet(pkt, size); 276cabdff1aSopenharmony_ci if (ret < 0) 277cabdff1aSopenharmony_ci return ret; 278cabdff1aSopenharmony_ci pkt->pos = pos; 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci pkt->data[0] = byte; 281cabdff1aSopenharmony_ci offset = 1; 282cabdff1aSopenharmony_ci pkt->duration = 240; 283cabdff1aSopenharmony_ci s->bit_rate = 8LL * size-- * st->codecpar->sample_rate * 512 / (506 * pkt->duration); 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ci pkt->stream_index = 0; 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci if (ctx->counter < size) { 288cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + offset, 289cabdff1aSopenharmony_ci ctx->counter); 290cabdff1aSopenharmony_ci if (ret < ctx->counter) 291cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR_EOF; 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci offset += ctx->counter; 294cabdff1aSopenharmony_ci size -= ctx->counter; 295cabdff1aSopenharmony_ci ctx->counter = 0; 296cabdff1aSopenharmony_ci dss_skip_audio_header(s, pkt); 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci ctx->counter -= size; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci ret = avio_read(s->pb, pkt->data + offset, size); 301cabdff1aSopenharmony_ci if (ret < size) 302cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR_EOF; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci return 0; 305cabdff1aSopenharmony_ci} 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_cistatic int dss_read_packet(AVFormatContext *s, AVPacket *pkt) 308cabdff1aSopenharmony_ci{ 309cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci if (ctx->audio_codec == DSS_ACODEC_DSS_SP) 312cabdff1aSopenharmony_ci return dss_sp_read_packet(s, pkt); 313cabdff1aSopenharmony_ci else 314cabdff1aSopenharmony_ci return dss_723_1_read_packet(s, pkt); 315cabdff1aSopenharmony_ci} 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_cistatic int dss_read_seek(AVFormatContext *s, int stream_index, 318cabdff1aSopenharmony_ci int64_t timestamp, int flags) 319cabdff1aSopenharmony_ci{ 320cabdff1aSopenharmony_ci DSSDemuxContext *ctx = s->priv_data; 321cabdff1aSopenharmony_ci int64_t ret, seekto; 322cabdff1aSopenharmony_ci uint8_t header[DSS_AUDIO_BLOCK_HEADER_SIZE]; 323cabdff1aSopenharmony_ci int offset; 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci if (ctx->audio_codec == DSS_ACODEC_DSS_SP) 326cabdff1aSopenharmony_ci seekto = timestamp / 264 * 41 / 506 * 512; 327cabdff1aSopenharmony_ci else 328cabdff1aSopenharmony_ci seekto = timestamp / 240 * ctx->packet_size / 506 * 512; 329cabdff1aSopenharmony_ci 330cabdff1aSopenharmony_ci if (seekto < 0) 331cabdff1aSopenharmony_ci seekto = 0; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci seekto += ctx->dss_header_size; 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci ret = avio_seek(s->pb, seekto, SEEK_SET); 336cabdff1aSopenharmony_ci if (ret < 0) 337cabdff1aSopenharmony_ci return ret; 338cabdff1aSopenharmony_ci 339cabdff1aSopenharmony_ci avio_read(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); 340cabdff1aSopenharmony_ci ctx->swap = !!(header[0] & 0x80); 341cabdff1aSopenharmony_ci offset = 2*header[1] + 2*ctx->swap; 342cabdff1aSopenharmony_ci if (offset < DSS_AUDIO_BLOCK_HEADER_SIZE) 343cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 344cabdff1aSopenharmony_ci if (offset == DSS_AUDIO_BLOCK_HEADER_SIZE) { 345cabdff1aSopenharmony_ci ctx->counter = 0; 346cabdff1aSopenharmony_ci offset = avio_skip(s->pb, -DSS_AUDIO_BLOCK_HEADER_SIZE); 347cabdff1aSopenharmony_ci } else { 348cabdff1aSopenharmony_ci ctx->counter = DSS_BLOCK_SIZE - offset; 349cabdff1aSopenharmony_ci offset = avio_skip(s->pb, offset - DSS_AUDIO_BLOCK_HEADER_SIZE); 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci ctx->dss_sp_swap_byte = -1; 352cabdff1aSopenharmony_ci return 0; 353cabdff1aSopenharmony_ci} 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ciconst AVInputFormat ff_dss_demuxer = { 357cabdff1aSopenharmony_ci .name = "dss", 358cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard (DSS)"), 359cabdff1aSopenharmony_ci .priv_data_size = sizeof(DSSDemuxContext), 360cabdff1aSopenharmony_ci .read_probe = dss_probe, 361cabdff1aSopenharmony_ci .read_header = dss_read_header, 362cabdff1aSopenharmony_ci .read_packet = dss_read_packet, 363cabdff1aSopenharmony_ci .read_seek = dss_read_seek, 364cabdff1aSopenharmony_ci .extensions = "dss" 365cabdff1aSopenharmony_ci}; 366