Petri Hintukainen wrote:
> Darren Salt wrote:
> > I've extracted the patches and added them (with minor tweaks) to the 1.1
> > patch queue.
>
> I'm also adding VC-1 video support, but there are some problems in
> ff_video_decoder.c. Opening ffmpeg VC-1 decoder fails and xine-lib
> ffmpeg wrapper plugin segfaults quite soon after that.
There are two tricks to make VC1 decoding work:
1) VC1 sequence and entry point headers must be present in
context->extradata.
2) video width and height must be known when opening decoder.
Some container formats store required extra data, but mpeg-ts does not.
1) is fixed by scanning the stream for headers and discarding all data
until proper headers are found.
2) is fixed by re-opening decoder with width and height information from
first open.
Proposed patches are attached. Any comments ?
- Petri
[xine-lib-1.1.16.3-ffmpeg-vc1-extradata.diff]
--- src/combined/ffmpeg/ff_video_decoder.c 2009-04-16 14:24:20.000000000 +0300
+++ src/combined/ffmpeg/ff_video_decoder.c 2009-09-24 15:21:25.000000000 +0300
@@ -1165,6 +1181,49 @@
}
}
+static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf)
+{
+ uint8_t *p = buf->content;
+
+ if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) {
+ int i;
+
+ this->context->extradata = calloc(1, buf->size);
+ this->context->extradata_size = 0;
+
+ for (i = 0; i < buf->size && i < 128; i++) {
+ if (!p[i] && !p[i+1] && p[i+2]) {
+ lprintf("00 00 01 %02x at %d\n", p[i+3], i);
+ if (p[i+3] != 0x0e && p[i+3] != 0x0f)
+ break;
+ }
+ this->context->extradata[i] = p[i];
+ this->context->extradata_size++;
+ }
+
+ lprintf("ff_video_decoder: found VC1 sequence header\n");
+ return 1;
+ }
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "ffmpeg_video_dec: VC1 extradata missing !\n");
+ return 0;
+}
+
+static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf)
+{
+ if (this->context && this->context->extradata)
+ return 1;
+
+ switch (codec_type) {
+ case BUF_VIDEO_VC1:
+ return ff_vc1_find_header(this, buf);
+ default:;
+ }
+
+ return 1;
+}
+
#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
uint8_t *chunk_buf = this->buf;
@@ -1176,6 +1235,9 @@
if (this->decoder_init_mode) {
int codec_type = buf->type & 0xFFFF0000;
+ if (!ff_check_extradata(this, codec_type, buf))
+ return;
+
/* init ffmpeg decoder */
init_video_codec(this, codec_type);
init_postprocess(this);
[xine-lib-1.1.16.3-ffmpeg-vc1-reopen.diff]
--- src/combined/ffmpeg/ff_video_decoder.c 2009-04-16 14:24:20.000000000 +0300
+++ src/combined/ffmpeg/ff_video_decoder.c 2009-09-24 15:21:25.000000000 +0300
@@ -340,6 +340,22 @@
return;
}
+ if (this->codec->id == CODEC_ID_VC1 &&
+ (!this->bih.biWidth || !this->bih.biHeight)) {
+ /* VC1 codec must be re-opened with correct width and height. */
+ avcodec_close(this->context);
+
+ if (avcodec_open (this->context, this->codec) < 0) {
+ pthread_mutex_unlock(&ffmpeg_lock);
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n"));
+ free(this->context);
+ this->context = NULL;
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+ return;
+ }
+ }
+
if (this->class->thread_count > 1) {
avcodec_thread_init(this->context, this->class->thread_count);
this->context->thread_count = this->class->thread_count;
------------------------------------------------------------------------------
Come build with us! The BlackBerry® Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9-12, 2009. Register now!
http://p.sf.net/sfu/devconf_______________________________________________
xine-devel mailing list
xine-devel@...
https://lists.sourceforge.net/lists/listinfo/xine-devel