diff --git a/libavformat/smacker.c b/libavformat/smacker.c index c803ecbec9..4990b7d920 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -48,14 +48,16 @@ typedef struct SmackerContext { uint32_t *frm_size; uint8_t *frm_flags; /* internal variables */ + int64_t next_frame_pos; int cur_frame; /* current frame for demuxing */ + uint32_t frame_size; + int flags; + int next_audio_index; + int new_palette; uint8_t pal[768]; int indexes[7]; int videoindex; - uint8_t *bufs[7]; - int buf_sizes[7]; - int stream_id[7]; int curstream; int64_t aud_pts[7]; } SmackerContext; @@ -235,21 +237,19 @@ static int smacker_read_header(AVFormatContext *s) static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) { SmackerContext *smk = s->priv_data; - int64_t next_frame_pos; int flags; int ret; - int i; - int frame_size = 0; - int palchange = 0; if (avio_feof(s->pb) || smk->cur_frame >= smk->frames) return AVERROR_EOF; /* if we demuxed all streams, pass another frame */ - if (smk->curstream <= 0) { - frame_size = smk->frm_size[smk->cur_frame] & (~3); - next_frame_pos = avio_tell(s->pb) + (unsigned)frame_size; + if (!smk->next_audio_index) { + smk->frame_size = smk->frm_size[smk->cur_frame] & (~3); + smk->next_frame_pos = avio_tell(s->pb) + smk->frame_size; + smk->curstream = 0; flags = smk->frm_flags[smk->cur_frame]; + smk->flags = flags >> 1; /* handle palette change event */ if(flags & SMACKER_PAL){ int size, sz, t, off, j, pos; @@ -258,13 +258,12 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) memcpy(oldpal, pal, 768); size = avio_r8(s->pb); - size = size * 4 - 1; - if (size + 1 > frame_size) { + size = size * 4; + if (size > smk->frame_size) { ret = AVERROR_INVALIDDATA; goto next_frame; } - frame_size -= size; - frame_size--; + smk->frame_size -= size--; sz = 0; pos = avio_tell(s->pb) + size; while(sz < 256){ @@ -298,69 +297,65 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) } } avio_seek(s->pb, pos, 0); - palchange |= 1; + smk->new_palette = 1; } - flags >>= 1; - smk->curstream = 0; - /* if audio chunks are present, put them to stack and retrieve later */ - for(i = 0; i < 7; i++) { - if(flags & 1) { + } + + for (int i = smk->next_audio_index; i < 7; i++) { + if (smk->flags & (1 << i)) { uint32_t size; size = avio_rl32(s->pb); - if ((int)size < 8 || size > frame_size) { + if ((int)size < 8 || size > smk->frame_size) { av_log(s, AV_LOG_ERROR, "Invalid audio part size\n"); ret = AVERROR_INVALIDDATA; goto next_frame; } - frame_size -= size; + smk->frame_size -= size; size -= 4; - if ((ret = av_reallocp(&smk->bufs[smk->curstream], size)) < 0) { - smk->buf_sizes[smk->curstream] = 0; + + if (smk->indexes[i] < 0) { + avio_skip(s->pb, size); + continue; + } + if ((ret = av_get_packet(s->pb, pkt, size)) != size) { + ret = ret < 0 ? ret : AVERROR_INVALIDDATA; goto next_frame; } - smk->buf_sizes[smk->curstream] = size; - ret = ffio_read_size(s->pb, smk->bufs[smk->curstream], size); - if (ret < 0) - goto next_frame; - smk->stream_id[smk->curstream] = smk->indexes[i]; + pkt->stream_index = smk->indexes[i]; + pkt->pts = smk->aud_pts[smk->curstream]; + smk->aud_pts[smk->curstream] += AV_RL32(pkt->data); + smk->next_audio_index = i + 1; smk->curstream++; + return 0; } - flags >>= 1; } - if (frame_size < 0 || frame_size >= INT_MAX/2) { + + if (smk->frame_size >= INT_MAX/2) { ret = AVERROR_INVALIDDATA; goto next_frame; } - if ((ret = av_new_packet(pkt, frame_size + 769)) < 0) + if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0) goto next_frame; + flags = smk->new_palette; if(smk->frm_size[smk->cur_frame] & 1) - palchange |= 2; - pkt->data[0] = palchange; + flags |= 2; + pkt->data[0] = flags; memcpy(pkt->data + 1, smk->pal, 768); - ret = ffio_read_size(s->pb, pkt->data + 769, frame_size); + ret = ffio_read_size(s->pb, pkt->data + 769, smk->frame_size); if (ret < 0) goto next_frame; pkt->stream_index = smk->videoindex; pkt->pts = smk->cur_frame; pkt->size = ret + 769; + smk->next_audio_index = 0; + smk->new_palette = 0; smk->cur_frame++; - } else { - smk->curstream--; - if (smk->stream_id[smk->curstream] < 0 || !smk->bufs[smk->curstream]) - return AVERROR_INVALIDDATA; - if ((ret = av_new_packet(pkt, smk->buf_sizes[smk->curstream])) < 0) - return ret; - memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]); - pkt->size = smk->buf_sizes[smk->curstream]; - pkt->stream_index = smk->stream_id[smk->curstream]; - pkt->pts = smk->aud_pts[smk->curstream]; - smk->aud_pts[smk->curstream] += AV_RL32(pkt->data); - } return 0; next_frame: - avio_seek(s->pb, next_frame_pos, SEEK_SET); + avio_seek(s->pb, smk->next_frame_pos, SEEK_SET); + smk->next_audio_index = 0; smk->cur_frame++; return ret; } @@ -368,10 +363,7 @@ next_frame: static int smacker_read_close(AVFormatContext *s) { SmackerContext *smk = s->priv_data; - int i; - for(i = 0; i < 7; i++) - av_freep(&smk->bufs[i]); av_freep(&smk->frm_size); av_freep(&smk->frm_flags);