Commit ba2c3850 authored by Hein-Pieter van Braam's avatar Hein-Pieter van Braam Committed by Paul B Mahol

Interplay MVE: Implement MVE SEND_BUFFER operation

Interplay MVE movies have a SEND_BUFFER operation. Only after this
command does the current decoding buffer get displayed. This is required
for the other frame formats. They are fixed-size and can't always encode
a full frame worth of pixeldata.

This code prevents half-finished frames from being emitted.
Signed-off-by: 's avatarHein-Pieter van Braam <hp@tmm.cx>
parent bbaca6e8
...@@ -990,17 +990,20 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, ...@@ -990,17 +990,20 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
IpvideoContext *s = avctx->priv_data; IpvideoContext *s = avctx->priv_data;
AVFrame *frame = data; AVFrame *frame = data;
int ret; int ret;
int send_buffer;
if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) { if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
av_frame_unref(s->last_frame); av_frame_unref(s->last_frame);
av_frame_unref(s->second_last_frame); av_frame_unref(s->second_last_frame);
} }
if (buf_size < 2) if (buf_size < 3)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
send_buffer = AV_RL8(avpkt->data);
/* decoding map contains 4 bits of information per 8x8 block */ /* decoding map contains 4 bits of information per 8x8 block */
s->decoding_map_size = AV_RL16(avpkt->data); s->decoding_map_size = AV_RL16(avpkt->data + 1);
/* compressed buffer needs to be large enough to at least hold an entire /* compressed buffer needs to be large enough to at least hold an entire
* decoding map */ * decoding map */
...@@ -1008,9 +1011,9 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, ...@@ -1008,9 +1011,9 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
return buf_size; return buf_size;
s->decoding_map = buf + 2; s->decoding_map = buf + 3;
bytestream2_init(&s->stream_ptr, buf + 2 + s->decoding_map_size, bytestream2_init(&s->stream_ptr, buf + 3 + s->decoding_map_size,
buf_size - s->decoding_map_size); buf_size - s->decoding_map_size - 3);
if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
return ret; return ret;
...@@ -1028,7 +1031,7 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, ...@@ -1028,7 +1031,7 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
ipvideo_decode_opcodes(s, frame); ipvideo_decode_opcodes(s, frame);
*got_frame = 1; *got_frame = send_buffer;
/* shuffle frames */ /* shuffle frames */
av_frame_unref(s->second_last_frame); av_frame_unref(s->second_last_frame);
......
...@@ -91,6 +91,7 @@ typedef struct IPMVEContext { ...@@ -91,6 +91,7 @@ typedef struct IPMVEContext {
uint32_t palette[256]; uint32_t palette[256];
int has_palette; int has_palette;
int changed; int changed;
uint8_t send_buffer;
unsigned int audio_bits; unsigned int audio_bits;
unsigned int audio_channels; unsigned int audio_channels;
...@@ -154,9 +155,9 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -154,9 +155,9 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
} else if (s->decode_map_chunk_offset) { } else if (s->decode_map_chunk_offset) {
/* send both the decode map and the video data together */ /* send the decode map, the video data, and the send_buffer flag together */
if (av_new_packet(pkt, 2 + s->decode_map_chunk_size + s->video_chunk_size)) if (av_new_packet(pkt, 3 + s->decode_map_chunk_size + s->video_chunk_size))
return CHUNK_NOMEM; return CHUNK_NOMEM;
if (s->has_palette) { if (s->has_palette) {
...@@ -178,8 +179,11 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -178,8 +179,11 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET); avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
s->decode_map_chunk_offset = 0; s->decode_map_chunk_offset = 0;
AV_WL16(pkt->data, s->decode_map_chunk_size); AV_WL8(pkt->data, s->send_buffer);
if (avio_read(pb, pkt->data + 2, s->decode_map_chunk_size) != s->send_buffer = 0;
AV_WL16(pkt->data + 1, s->decode_map_chunk_size);
if (avio_read(pb, pkt->data + 3, s->decode_map_chunk_size) !=
s->decode_map_chunk_size) { s->decode_map_chunk_size) {
av_packet_unref(pkt); av_packet_unref(pkt);
return CHUNK_EOF; return CHUNK_EOF;
...@@ -188,7 +192,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, ...@@ -188,7 +192,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
avio_seek(pb, s->video_chunk_offset, SEEK_SET); avio_seek(pb, s->video_chunk_offset, SEEK_SET);
s->video_chunk_offset = 0; s->video_chunk_offset = 0;
if (avio_read(pb, pkt->data + 2 + s->decode_map_chunk_size, if (avio_read(pb, pkt->data + 3 + s->decode_map_chunk_size,
s->video_chunk_size) != s->video_chunk_size) { s->video_chunk_size) != s->video_chunk_size) {
av_packet_unref(pkt); av_packet_unref(pkt);
return CHUNK_EOF; return CHUNK_EOF;
...@@ -444,6 +448,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, ...@@ -444,6 +448,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
case OPCODE_SEND_BUFFER: case OPCODE_SEND_BUFFER:
av_log(s->avf, AV_LOG_TRACE, "send buffer\n"); av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
avio_skip(pb, opcode_size); avio_skip(pb, opcode_size);
s->send_buffer = 1;
break; break;
case OPCODE_AUDIO_FRAME: case OPCODE_AUDIO_FRAME:
...@@ -590,6 +595,7 @@ static int ipmovie_read_header(AVFormatContext *s) ...@@ -590,6 +595,7 @@ static int ipmovie_read_header(AVFormatContext *s)
ipmovie->video_pts = ipmovie->audio_frame_count = 0; ipmovie->video_pts = ipmovie->audio_frame_count = 0;
ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
ipmovie->decode_map_chunk_offset = 0; ipmovie->decode_map_chunk_offset = 0;
ipmovie->send_buffer = 0;
/* on the first read, this will position the stream at the first chunk */ /* on the first read, this will position the stream at the first chunk */
ipmovie->next_chunk_offset = avio_tell(pb) + 4; ipmovie->next_chunk_offset = avio_tell(pb) + 4;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment