matroskadec: split frame parsing
This commit is contained in:
		
							parent
							
								
									2d0e7713f9
								
							
						
					
					
						commit
						c831ebf616
					
				@ -1855,6 +1855,141 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
 | 
			
		||||
                                   MatroskaTrack *track,
 | 
			
		||||
                                   AVStream *st,
 | 
			
		||||
                                   uint8_t *data, int size,
 | 
			
		||||
                                   uint64_t timecode, uint64_t duration,
 | 
			
		||||
                                   int64_t pos)
 | 
			
		||||
{
 | 
			
		||||
    int a = st->codec->block_align;
 | 
			
		||||
    int sps = track->audio.sub_packet_size;
 | 
			
		||||
    int cfs = track->audio.coded_framesize;
 | 
			
		||||
    int h = track->audio.sub_packet_h;
 | 
			
		||||
    int y = track->audio.sub_packet_cnt;
 | 
			
		||||
    int w = track->audio.frame_size;
 | 
			
		||||
    int x;
 | 
			
		||||
 | 
			
		||||
    if (!track->audio.pkt_cnt) {
 | 
			
		||||
        if (track->audio.sub_packet_cnt == 0)
 | 
			
		||||
            track->audio.buf_timecode = timecode;
 | 
			
		||||
        if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
 | 
			
		||||
            if (size < cfs * h / 2) {
 | 
			
		||||
                av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                       "Corrupt int4 RM-style audio packet size\n");
 | 
			
		||||
                return AVERROR_INVALIDDATA;
 | 
			
		||||
            }
 | 
			
		||||
            for (x=0; x<h/2; x++)
 | 
			
		||||
                memcpy(track->audio.buf+x*2*w+y*cfs,
 | 
			
		||||
                       data+x*cfs, cfs);
 | 
			
		||||
        } else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
 | 
			
		||||
            if (size < w) {
 | 
			
		||||
                av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                       "Corrupt sipr RM-style audio packet size\n");
 | 
			
		||||
                return AVERROR_INVALIDDATA;
 | 
			
		||||
            }
 | 
			
		||||
            memcpy(track->audio.buf + y*w, data, w);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (size < sps * w / sps) {
 | 
			
		||||
                av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                       "Corrupt generic RM-style audio packet size\n");
 | 
			
		||||
                return AVERROR_INVALIDDATA;
 | 
			
		||||
            }
 | 
			
		||||
            for (x=0; x<w/sps; x++)
 | 
			
		||||
                memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (++track->audio.sub_packet_cnt >= h) {
 | 
			
		||||
            if (st->codec->codec_id == AV_CODEC_ID_SIPR)
 | 
			
		||||
                ff_rm_reorder_sipr_data(track->audio.buf, h, w);
 | 
			
		||||
            track->audio.sub_packet_cnt = 0;
 | 
			
		||||
            track->audio.pkt_cnt = h*w / a;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (track->audio.pkt_cnt) {
 | 
			
		||||
        AVPacket *pkt = av_mallocz(sizeof(AVPacket));
 | 
			
		||||
        av_new_packet(pkt, a);
 | 
			
		||||
        memcpy(pkt->data, track->audio.buf
 | 
			
		||||
               + a * (h*w / a - track->audio.pkt_cnt--), a);
 | 
			
		||||
        pkt->pts = track->audio.buf_timecode;
 | 
			
		||||
        track->audio.buf_timecode = AV_NOPTS_VALUE;
 | 
			
		||||
        pkt->pos = pos;
 | 
			
		||||
        pkt->stream_index = st->index;
 | 
			
		||||
        dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
 | 
			
		||||
                                MatroskaTrack *track,
 | 
			
		||||
                                AVStream *st,
 | 
			
		||||
                                uint8_t *data, int pkt_size,
 | 
			
		||||
                                uint64_t timecode, uint64_t duration,
 | 
			
		||||
                                int64_t pos, int is_keyframe)
 | 
			
		||||
{
 | 
			
		||||
    MatroskaTrackEncoding *encodings = track->encodings.elem;
 | 
			
		||||
    uint8_t *pkt_data = data;
 | 
			
		||||
    int offset = 0, res;
 | 
			
		||||
    AVPacket *pkt;
 | 
			
		||||
 | 
			
		||||
    if (encodings && encodings->scope & 1) {
 | 
			
		||||
        res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
 | 
			
		||||
        if (res < 0)
 | 
			
		||||
            return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (st->codec->codec_id == AV_CODEC_ID_PRORES)
 | 
			
		||||
        offset = 8;
 | 
			
		||||
 | 
			
		||||
    pkt = av_mallocz(sizeof(AVPacket));
 | 
			
		||||
    /* XXX: prevent data copy... */
 | 
			
		||||
    if (av_new_packet(pkt, pkt_size + offset) < 0) {
 | 
			
		||||
        av_free(pkt);
 | 
			
		||||
        return AVERROR(ENOMEM);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
 | 
			
		||||
        uint8_t *buf = pkt->data;
 | 
			
		||||
        bytestream_put_be32(&buf, pkt_size);
 | 
			
		||||
        bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(pkt->data + offset, pkt_data, pkt_size);
 | 
			
		||||
 | 
			
		||||
    if (pkt_data != data)
 | 
			
		||||
        av_free(pkt_data);
 | 
			
		||||
 | 
			
		||||
    pkt->flags = is_keyframe;
 | 
			
		||||
    pkt->stream_index = st->index;
 | 
			
		||||
 | 
			
		||||
    if (track->ms_compat)
 | 
			
		||||
        pkt->dts = timecode;
 | 
			
		||||
    else
 | 
			
		||||
        pkt->pts = timecode;
 | 
			
		||||
    pkt->pos = pos;
 | 
			
		||||
    if (st->codec->codec_id == AV_CODEC_ID_TEXT)
 | 
			
		||||
        pkt->convergence_duration = duration;
 | 
			
		||||
    else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE)
 | 
			
		||||
        pkt->duration = duration;
 | 
			
		||||
 | 
			
		||||
    if (st->codec->codec_id == AV_CODEC_ID_SSA)
 | 
			
		||||
        matroska_fix_ass_packet(matroska, pkt, duration);
 | 
			
		||||
 | 
			
		||||
    if (matroska->prev_pkt &&
 | 
			
		||||
        timecode != AV_NOPTS_VALUE &&
 | 
			
		||||
        matroska->prev_pkt->pts == timecode &&
 | 
			
		||||
        matroska->prev_pkt->stream_index == st->index &&
 | 
			
		||||
        st->codec->codec_id == AV_CODEC_ID_SSA)
 | 
			
		||||
        matroska_merge_packets(matroska->prev_pkt, pkt);
 | 
			
		||||
    else {
 | 
			
		||||
        dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
 | 
			
		||||
        matroska->prev_pkt = pkt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
 | 
			
		||||
                                int size, int64_t pos, uint64_t cluster_time,
 | 
			
		||||
                                uint64_t duration, int is_keyframe,
 | 
			
		||||
@ -1864,7 +1999,6 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
 | 
			
		||||
    MatroskaTrack *track;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    AVStream *st;
 | 
			
		||||
    AVPacket *pkt;
 | 
			
		||||
    int16_t block_time;
 | 
			
		||||
    uint32_t *lace_size = NULL;
 | 
			
		||||
    int n, flags, laces = 0;
 | 
			
		||||
@ -1917,139 +2051,33 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
 | 
			
		||||
    res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1,
 | 
			
		||||
                               &lace_size, &laces);
 | 
			
		||||
 | 
			
		||||
    if (res == 0) {
 | 
			
		||||
        for (n = 0; n < laces; n++) {
 | 
			
		||||
            if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
 | 
			
		||||
                 st->codec->codec_id == AV_CODEC_ID_COOK ||
 | 
			
		||||
                 st->codec->codec_id == AV_CODEC_ID_SIPR ||
 | 
			
		||||
                 st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
 | 
			
		||||
                 st->codec->block_align && track->audio.sub_packet_size) {
 | 
			
		||||
                int a = st->codec->block_align;
 | 
			
		||||
                int sps = track->audio.sub_packet_size;
 | 
			
		||||
                int cfs = track->audio.coded_framesize;
 | 
			
		||||
                int h = track->audio.sub_packet_h;
 | 
			
		||||
                int y = track->audio.sub_packet_cnt;
 | 
			
		||||
                int w = track->audio.frame_size;
 | 
			
		||||
                int x;
 | 
			
		||||
    if (res)
 | 
			
		||||
        goto end;
 | 
			
		||||
 | 
			
		||||
                if (!track->audio.pkt_cnt) {
 | 
			
		||||
                    if (track->audio.sub_packet_cnt == 0)
 | 
			
		||||
                        track->audio.buf_timecode = timecode;
 | 
			
		||||
                    if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
 | 
			
		||||
                        if (size < cfs * h / 2) {
 | 
			
		||||
                            av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                                   "Corrupt int4 RM-style audio packet size\n");
 | 
			
		||||
                            res = AVERROR_INVALIDDATA;
 | 
			
		||||
                            goto end;
 | 
			
		||||
                        }
 | 
			
		||||
                        for (x=0; x<h/2; x++)
 | 
			
		||||
                            memcpy(track->audio.buf+x*2*w+y*cfs,
 | 
			
		||||
                                   data+x*cfs, cfs);
 | 
			
		||||
                    } else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
 | 
			
		||||
                        if (size < w) {
 | 
			
		||||
                            av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                                   "Corrupt sipr RM-style audio packet size\n");
 | 
			
		||||
                            res = AVERROR_INVALIDDATA;
 | 
			
		||||
                            goto end;
 | 
			
		||||
                        }
 | 
			
		||||
                        memcpy(track->audio.buf + y*w, data, w);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (size < sps * w / sps) {
 | 
			
		||||
                            av_log(matroska->ctx, AV_LOG_ERROR,
 | 
			
		||||
                                   "Corrupt generic RM-style audio packet size\n");
 | 
			
		||||
                            res = AVERROR_INVALIDDATA;
 | 
			
		||||
                            goto end;
 | 
			
		||||
                        }
 | 
			
		||||
                        for (x=0; x<w/sps; x++)
 | 
			
		||||
                            memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
 | 
			
		||||
                    }
 | 
			
		||||
    for (n = 0; n < laces; n++) {
 | 
			
		||||
        if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
 | 
			
		||||
             st->codec->codec_id == AV_CODEC_ID_COOK ||
 | 
			
		||||
             st->codec->codec_id == AV_CODEC_ID_SIPR ||
 | 
			
		||||
             st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
 | 
			
		||||
             st->codec->block_align && track->audio.sub_packet_size) {
 | 
			
		||||
 | 
			
		||||
                    if (++track->audio.sub_packet_cnt >= h) {
 | 
			
		||||
                        if (st->codec->codec_id == AV_CODEC_ID_SIPR)
 | 
			
		||||
                            ff_rm_reorder_sipr_data(track->audio.buf, h, w);
 | 
			
		||||
                        track->audio.sub_packet_cnt = 0;
 | 
			
		||||
                        track->audio.pkt_cnt = h*w / a;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                while (track->audio.pkt_cnt) {
 | 
			
		||||
                    pkt = av_mallocz(sizeof(AVPacket));
 | 
			
		||||
                    av_new_packet(pkt, a);
 | 
			
		||||
                    memcpy(pkt->data, track->audio.buf
 | 
			
		||||
                           + a * (h*w / a - track->audio.pkt_cnt--), a);
 | 
			
		||||
                    pkt->pts = track->audio.buf_timecode;
 | 
			
		||||
                    track->audio.buf_timecode = AV_NOPTS_VALUE;
 | 
			
		||||
                    pkt->pos = pos;
 | 
			
		||||
                    pkt->stream_index = st->index;
 | 
			
		||||
                    dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                MatroskaTrackEncoding *encodings = track->encodings.elem;
 | 
			
		||||
                uint32_t pkt_size = lace_size[n];
 | 
			
		||||
                uint8_t *pkt_data = data;
 | 
			
		||||
                int offset = 0;
 | 
			
		||||
            res = matroska_parse_rm_audio(matroska, track, st, data, size,
 | 
			
		||||
                                          timecode, duration, pos);
 | 
			
		||||
            if (res)
 | 
			
		||||
                goto end;
 | 
			
		||||
 | 
			
		||||
                if (encodings && encodings->scope & 1) {
 | 
			
		||||
                    res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
 | 
			
		||||
                    if (res < 0)
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (st->codec->codec_id == AV_CODEC_ID_PRORES)
 | 
			
		||||
                    offset = 8;
 | 
			
		||||
 | 
			
		||||
                pkt = av_mallocz(sizeof(AVPacket));
 | 
			
		||||
                /* XXX: prevent data copy... */
 | 
			
		||||
                if (av_new_packet(pkt, pkt_size + offset) < 0) {
 | 
			
		||||
                    av_free(pkt);
 | 
			
		||||
                    res = AVERROR(ENOMEM);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
 | 
			
		||||
                    uint8_t *buf = pkt->data;
 | 
			
		||||
                    bytestream_put_be32(&buf, pkt_size);
 | 
			
		||||
                    bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                memcpy(pkt->data + offset, pkt_data, pkt_size);
 | 
			
		||||
 | 
			
		||||
                if (pkt_data != data)
 | 
			
		||||
                    av_free(pkt_data);
 | 
			
		||||
 | 
			
		||||
                if (n == 0)
 | 
			
		||||
                    pkt->flags = is_keyframe;
 | 
			
		||||
                pkt->stream_index = st->index;
 | 
			
		||||
 | 
			
		||||
                if (track->ms_compat)
 | 
			
		||||
                    pkt->dts = timecode;
 | 
			
		||||
                else
 | 
			
		||||
                    pkt->pts = timecode;
 | 
			
		||||
                pkt->pos = pos;
 | 
			
		||||
                if (st->codec->codec_id == AV_CODEC_ID_TEXT)
 | 
			
		||||
                    pkt->convergence_duration = duration;
 | 
			
		||||
                else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE)
 | 
			
		||||
                    pkt->duration = duration;
 | 
			
		||||
 | 
			
		||||
                if (st->codec->codec_id == AV_CODEC_ID_SSA)
 | 
			
		||||
                    matroska_fix_ass_packet(matroska, pkt, duration);
 | 
			
		||||
 | 
			
		||||
                if (matroska->prev_pkt &&
 | 
			
		||||
                    timecode != AV_NOPTS_VALUE &&
 | 
			
		||||
                    matroska->prev_pkt->pts == timecode &&
 | 
			
		||||
                    matroska->prev_pkt->stream_index == st->index &&
 | 
			
		||||
                    st->codec->codec_id == AV_CODEC_ID_SSA)
 | 
			
		||||
                    matroska_merge_packets(matroska->prev_pkt, pkt);
 | 
			
		||||
                else {
 | 
			
		||||
                    dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
 | 
			
		||||
                    matroska->prev_pkt = pkt;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (timecode != AV_NOPTS_VALUE)
 | 
			
		||||
                timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
 | 
			
		||||
            data += lace_size[n];
 | 
			
		||||
            size -= lace_size[n];
 | 
			
		||||
        } else {
 | 
			
		||||
            res = matroska_parse_frame(matroska, track, st, data, lace_size[n],
 | 
			
		||||
                                      timecode, duration,
 | 
			
		||||
                                      pos, !n? is_keyframe : 0);
 | 
			
		||||
            if (res)
 | 
			
		||||
                goto end;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (timecode != AV_NOPTS_VALUE)
 | 
			
		||||
            timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
 | 
			
		||||
        data += lace_size[n];
 | 
			
		||||
        size -= lace_size[n];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user