diff options
Diffstat (limited to 'xine')
-rw-r--r-- | xine/demux_xvdr.c | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/xine/demux_xvdr.c b/xine/demux_xvdr.c index a555c6ec..32947039 100644 --- a/xine/demux_xvdr.c +++ b/xine/demux_xvdr.c @@ -196,6 +196,26 @@ static void put_control_buf(fifo_buffer_t *buffer, fifo_buffer_t *pool, int cmd) } /* + * post_sequence_end() + * + * Add MPEG2 or H.264 sequence end code to fifo buffer + */ +static void post_sequence_end(fifo_buffer_t *fifo, uint32_t video_type) +{ + buf_element_t *buf = fifo->buffer_pool_try_alloc(fifo); + if (buf) { + buf->type = video_type; + buf->size = 4; + buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->content[0] = 0x00; + buf->content[1] = 0x00; + buf->content[2] = 0x01; + buf->content[3] = (video_type == BUF_VIDEO_H264) ? NAL_END_SEQ : 0xB7; + fifo->put(fifo, buf); + } +} + +/* * post_frame_end() * * Signal end of video frame to decoder. @@ -298,62 +318,74 @@ static void track_audio_stream_change(demux_xvdr_t *this, buf_element_t *buf) #endif } -static void demux_xvdr_parse_pack (demux_xvdr_t *this) +static void demux_xvdr_fwd_buf(demux_xvdr_t *this, buf_element_t *buf) { - buf_element_t *buf = NULL; - uint8_t *p; - - buf = this->input->read_block (this->input, this->video_fifo, 8128); - - if (!buf) { - if (errno != EAGAIN) - this->status = DEMUX_FINISHED; + /* demuxed video --> video_fifo */ + if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) { + this->video_type = buf->type; + check_newpts (this, buf, PTS_VIDEO); + this->video_fifo->put (this->video_fifo, buf); return; } - /* If this is not a block for the demuxer, pass it - * straight through. */ - if (buf->type != BUF_DEMUX_BLOCK) { - - if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) { - check_newpts (this, buf, PTS_VIDEO); - this->video_fifo->put (this->video_fifo, buf); - return; - } - - if ((buf->type & BUF_MAJOR_MASK) == BUF_AUDIO_BASE) { - if (this->audio_fifo) { - check_newpts (this, buf, PTS_AUDIO); - track_audio_stream_change (this, buf); - this->audio_fifo->put (this->audio_fifo, buf); - } else { - buf->free_buffer (buf); - } - return; - } - - if (buf->type == BUF_CONTROL_FLUSH_DECODER) { - /* decoder flush only to video fifo */ - this->stream->video_fifo->put(this->stream->video_fifo, buf); - return; + /* demuxed audio --> audio_fifo */ + if ((buf->type & BUF_MAJOR_MASK) == BUF_AUDIO_BASE) { + if (this->audio_fifo) { + check_newpts (this, buf, PTS_AUDIO); + track_audio_stream_change (this, buf); + this->audio_fifo->put (this->audio_fifo, buf); + } else { + buf->free_buffer (buf); } + return; + } - if ((buf->type & BUF_MAJOR_MASK) != BUF_CONTROL_BASE) - LOGMSG("buffer type %08x != BUF_DEMUX_BLOCK", buf->type); + /* decoder flush --> video_fifo */ + if (buf->type == BUF_CONTROL_FLUSH_DECODER) { + /* append sequence end code */ + post_sequence_end (this->video_fifo, this->video_type); + this->video_fifo->put (this->video_fifo, buf); + return; + } - /* duplicate goes to audio fifo */ + /* control buffer --> both fifos */ + if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE) { if (this->audio_fifo) { + /* duplicate goes to audio fifo */ buf_element_t *cbuf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - cbuf->type = buf->type; cbuf->decoder_flags = buf->decoder_flags; - memcpy( cbuf->decoder_info, buf->decoder_info, sizeof(cbuf->decoder_info) ); - memcpy( cbuf->decoder_info_ptr, buf->decoder_info_ptr, sizeof(cbuf->decoder_info_ptr) ); + memcpy (cbuf->decoder_info, buf->decoder_info, sizeof(cbuf->decoder_info)); + memcpy (cbuf->decoder_info_ptr, buf->decoder_info_ptr, sizeof(cbuf->decoder_info_ptr)); this->audio_fifo->put (this->audio_fifo, cbuf); } this->video_fifo->put (this->video_fifo, buf); + return; + } + + LOGMSG("Unhandled buffer type %08x", buf->type); + buf->free_buffer (buf); +} + +static void demux_xvdr_parse_pack (demux_xvdr_t *this) +{ + buf_element_t *buf = NULL; + uint8_t *p; + buf = this->input->read_block (this->input, this->video_fifo, 8128); + + if (!buf) { + if (errno != EAGAIN) + this->status = DEMUX_FINISHED; + return; + } + + /* If this is not a block for the demuxer, pass it + * straight through. */ + if (buf->type != BUF_DEMUX_BLOCK) { + ts_data_flush (this->ts_data); + demux_xvdr_fwd_buf (this, buf); return; } |