static int spdif_probe(AVProbeData *p) { const uint8_t *buf = p->buf; const uint8_t *probe_end = p->buf + FFMIN(2 * SPDIF_MAX_OFFSET, p->buf_size - 1); const uint8_t *expected_code = buf + 7; uint32_t state = 0; int sync_codes = 0; int consecutive_codes = 0; int offset; enum CodecID codec; for (; buf < probe_end; buf++) { state = (state << 8) | *buf; if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2)) && buf[1] < 0x37) { sync_codes++; if (buf == expected_code) { if (++consecutive_codes >= 2) return AVPROBE_SCORE_MAX; } else consecutive_codes = 0; if (buf + 4 + AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size) break; /* continue probing to find more sync codes */ probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p->buf + p->buf_size - 1); /* skip directly to the next sync code */ if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1], &buf[5], &offset, &codec)) { if (buf + offset >= p->buf + p->buf_size) break; expected_code = buf + offset; buf = expected_code - 7; } } } if (!sync_codes) return 0; if (sync_codes >= 6) /* good amount of sync codes but with unexpected offsets */ return AVPROBE_SCORE_MAX / 2; /* some sync codes were found */ return AVPROBE_SCORE_MAX / 8; }
static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; enum IEC61937DataType data_type; enum CodecID codec_id; uint32_t state = 0; int pkt_size_bits, offset, ret; while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) { state = (state << 8) | avio_r8(pb); if (url_feof(pb)) return AVERROR_EOF; } data_type = avio_rl16(pb); pkt_size_bits = avio_rl16(pb); if (pkt_size_bits % 16) av_log_ask_for_sample(s, "Packet does not end to a 16-bit boundary."); ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3); if (ret) return ret; pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { av_free_packet(pkt); return AVERROR_EOF; } ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); ret = spdif_get_offset_and_codec(s, data_type, pkt->data, &offset, &codec_id); if (ret) { av_free_packet(pkt); return ret; } /* skip over the padding to the beginning of the next frame */ avio_skip(pb, offset - pkt->size - BURST_HEADER_SIZE); if (!s->nb_streams) { /* first packet, create a stream */ AVStream *st = av_new_stream(s, 0); if (!st) { av_free_packet(pkt); return AVERROR(ENOMEM); } st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = codec_id; } else if (codec_id != s->streams[0]->codec->codec_id) { av_log_missing_feature(s, "codec change in IEC 61937", 0); return AVERROR_PATCHWELCOME; } if (!s->bit_rate && s->streams[0]->codec->sample_rate) /* stream bitrate matches 16-bit stereo PCM bitrate for currently supported codecs */ s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate; return 0; }
int my_spdif_read_packet(AVFormatContext *s, AVPacket *pkt, uint8_t * garbagebuffer, int garbagebuffersize, int * garbagebufferfilled) { AVIOContext *pb = s->pb; enum IEC61937DataType data_type; enum AVCodecID codec_id; uint32_t state = 0; int pkt_size_bits, offset, ret; *garbagebufferfilled = 0; while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) { if(*garbagebufferfilled < garbagebuffersize){ *garbagebuffer = avio_r8(pb); (*garbagebufferfilled)++; state = (state << 8) | *garbagebuffer; garbagebuffer++; if (avio_feof(pb)){ return AVERROR_EOF; } }else{ return AVERROR_STREAM_NOT_FOUND; } } *garbagebufferfilled -= 4; data_type = avio_rl16(pb); pkt_size_bits = avio_rl16(pb); if (pkt_size_bits % 16) avpriv_request_sample(s, "Packet not ending at a 16-bit boundary"); ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3); if (ret) return ret; pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { av_free_packet(pkt); return AVERROR_EOF; } my_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); ret = spdif_get_offset_and_codec(s, data_type, pkt->data, &offset, &codec_id); if (ret) { av_free_packet(pkt); return ret; } /* skip over the padding to the beginning of the next frame */ avio_skip(pb, offset - pkt->size - BURST_HEADER_SIZE); if (!s->nb_streams) { /* first packet, create a stream */ AVStream *st = avformat_new_stream(s, NULL); if (!st) { av_free_packet(pkt); return AVERROR(ENOMEM); } st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = codec_id; } else if (codec_id != s->streams[0]->codec->codec_id) { avpriv_report_missing_feature(s, "Codec change in IEC 61937"); return AVERROR_PATCHWELCOME; } if (!s->bit_rate && s->streams[0]->codec->sample_rate) /* stream bitrate matches 16-bit stereo PCM bitrate for currently supported codecs */ s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate; return 0; }