X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fdsfdec.c;h=52cddab2c8b75123e32a3d5224dd1c1c2061518e;hb=6a7b5226e1c868fe6406b114e7303c70d886900b;hp=41538fd83c0c16397178a57160443b6bd166403e;hpb=f61cf0e4df52130c138ee55691409044ab2e9833;p=ffmpeg diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c index 41538fd83c0..52cddab2c8b 100644 --- a/libavformat/dsfdec.c +++ b/libavformat/dsfdec.c @@ -26,9 +26,11 @@ typedef struct { uint64_t data_end; + uint64_t audio_size; + uint64_t data_size; } DSFContext; -static int dsf_probe(AVProbeData *p) +static int dsf_probe(const AVProbeData *p) { if (p->buf_size < 12 || memcmp(p->buf, "DSD ", 4) || AV_RL64(p->buf + 4) != 28) return 0; @@ -120,7 +122,7 @@ static int dsf_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - avio_skip(pb, 8); + dsf->audio_size = avio_rl64(pb) / 8 * st->codecpar->channels; st->codecpar->block_align = avio_rl32(pb); if (st->codecpar->block_align > INT_MAX / st->codecpar->channels) { avpriv_request_sample(s, "block_align overflow"); @@ -128,6 +130,7 @@ static int dsf_read_header(AVFormatContext *s) } st->codecpar->block_align *= st->codecpar->channels; st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * 8LL; + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(pb, 4); /* data chunk */ @@ -135,7 +138,9 @@ static int dsf_read_header(AVFormatContext *s) dsf->data_end = avio_tell(pb); if (avio_rl32(pb) != MKTAG('d', 'a', 't', 'a')) return AVERROR_INVALIDDATA; - dsf->data_end += avio_rl64(pb); + dsf->data_size = avio_rl64(pb) - 12; + dsf->data_end += dsf->data_size + 12; + s->internal->data_offset = avio_tell(pb); return 0; } @@ -146,12 +151,52 @@ static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int64_t pos = avio_tell(pb); + int ret; if (pos >= dsf->data_end) return AVERROR_EOF; + if (dsf->data_size > dsf->audio_size) { + int last_packet = pos == (dsf->data_end - st->codecpar->block_align); + + if (last_packet) { + int64_t data_pos = pos - s->internal->data_offset; + int64_t packet_size = dsf->audio_size - data_pos; + int64_t skip_size = dsf->data_size - data_pos - packet_size; + uint8_t *dst; + int ch, ret; + + if (packet_size <= 0 || skip_size <= 0) + return AVERROR_INVALIDDATA; + + if ((ret = av_new_packet(pkt, packet_size)) < 0) + return ret; + dst = pkt->data; + for (ch = 0; ch < st->codecpar->channels; ch++) { + ret = avio_read(pb, dst, packet_size / st->codecpar->channels); + if (ret < packet_size / st->codecpar->channels) + return AVERROR_EOF; + + dst += ret; + avio_skip(pb, skip_size / st->codecpar->channels); + } + + pkt->pos = pos; + pkt->stream_index = 0; + pkt->pts = (pos - s->internal->data_offset) / st->codecpar->channels; + pkt->duration = packet_size / st->codecpar->channels; + return 0; + } + } + ret = av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codecpar->block_align)); + if (ret < 0) + return ret; + pkt->stream_index = 0; - return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codecpar->block_align)); + pkt->pts = (pos - s->internal->data_offset) / st->codecpar->channels; + pkt->duration = st->codecpar->block_align / st->codecpar->channels; + + return 0; } AVInputFormat ff_dsf_demuxer = {