summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2007-11-01 00:14:33 +0100
committerReinhard Nißl <rnissl@gmx.de>2007-11-01 00:14:33 +0100
commite2aafb0f72934a33a9318faf411c79b4cf170428 (patch)
tree6379edfec296dc9abdd8d0e1aa060e79c20e32e2
parent33ab5ef7247bc4694d00b5e96f32ec1b1d4a6357 (diff)
downloadxine-lib-e2aafb0f72934a33a9318faf411c79b4cf170428.tar.gz
xine-lib-e2aafb0f72934a33a9318faf411c79b4cf170428.tar.bz2
Improve interfacing FFmpeg especially for interlaced content.
The changes include setting VO_INTERLACED_FLAG for interlaced frames, adjusting frame height to a multiple of 32 lines (i. e. the height of one macroblock per field) and cropping away the extra lines, setting progressive_frame and top_field_first as supplied by FFmpeg, fixing the workaround for demux_mpep_pes sending fields as frames and bad frame allocation (i. e. use at least 16x32 pixels). --HG-- extra : transplant_source : %C7c%951J%F5o%C5%F1%16%B4%05%95%D0J%C0j%7F%E6%F8
-rw-r--r--src/libffmpeg/ff_video_decoder.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/src/libffmpeg/ff_video_decoder.c b/src/libffmpeg/ff_video_decoder.c
index 83c3f2945..e81e963ab 100644
--- a/src/libffmpeg/ff_video_decoder.c
+++ b/src/libffmpeg/ff_video_decoder.c
@@ -1157,6 +1157,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
int offset = 0;
int codec_type = buf->type & 0xFFFF0000;
int video_step_to_use;
+ int frame_flags_to_use;
/* pad input data */
/* note: bitstream, alt bitstream reader or something will cause
@@ -1200,6 +1201,12 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
/* use externally provided video_step or fall back to stream's time_base otherwise */
video_step_to_use = (this->video_step || !this->context->time_base.den) ? this->video_step : (int)(90000ll * this->context->time_base.num / this->context->time_base.den);
+ frame_flags_to_use = this->frame_flags;
+
+ /* adjust frame flags for interlaced frames when running in demux_mpeg_pes context */
+ if (!this->video_step && this->av_frame->interlaced_frame)
+ frame_flags_to_use |= VO_INTERLACED_FLAG;
+
/* aspect ratio provided by ffmpeg, override previous setting */
if ((this->aspect_ratio_prio < 2) &&
av_cmp_q(this->context->sample_aspect_ratio, avr00)) {
@@ -1246,10 +1253,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
img = this->stream->video_out->get_frame (this->stream->video_out,
this->bih.biWidth,
- this->bih.biHeight,
+ (this->bih.biHeight + 31) & ~31,
this->aspect_ratio,
this->output_format,
- VO_BOTH_FIELDS|this->frame_flags);
+ VO_BOTH_FIELDS|frame_flags_to_use);
free_img = 1;
} else {
/* DR1 */
@@ -1267,10 +1274,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
/* DR1 */
img = this->stream->video_out->get_frame (this->stream->video_out,
img->width,
- img->height,
+ (img->height + 31) & ~31,
this->aspect_ratio,
this->output_format,
- VO_BOTH_FIELDS|this->frame_flags);
+ VO_BOTH_FIELDS|frame_flags_to_use);
free_img = 1;
}
@@ -1289,10 +1296,6 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
img->pts = this->pts;
this->pts = 0;
- /* workaround for demux_mpeg_pes sending fields as frames */
- if (!this->video_step && this->av_frame->interlaced_frame)
- video_step_to_use /= 2;
-
/* workaround for weird 120fps streams */
if( video_step_to_use == 750 ) {
/* fallback to the VIDEO_PTS_MODE */
@@ -1305,8 +1308,14 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
img->duration = video_step_to_use;
img->crop_right = this->crop_right;
- img->crop_bottom = this->crop_bottom;
-
+ img->crop_bottom = this->crop_bottom + (img->height - this->bih.biHeight);
+
+ /* transfer some more frame settings when running in demux_mpeg_pes context */
+ if (!this->video_step) {
+ img->progressive_frame = !this->av_frame->interlaced_frame;
+ img->top_field_first = this->av_frame->top_field_first;
+ }
+
this->skipframes = img->draw(img, this->stream);
if(free_img)
@@ -1314,19 +1323,27 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
}
}
- if (!got_one_picture) {
+ /* workaround for demux_mpeg_pes sending fields as frames:
+ * do not generate a bad frame for the first field picture
+ */
+ if (!got_one_picture && (this->size || this->video_step || !this->av_frame->interlaced_frame)) {
/* skipped frame, output a bad frame (of size 1x1 when size still uninitialized) */
img = this->stream->video_out->get_frame (this->stream->video_out,
- (this->bih.biWidth <= 0) ? 1 : this->bih.biWidth,
- (this->bih.biHeight <= 0) ? 1 : this->bih.biHeight,
+ (this->bih.biWidth <= 0) ? 16 : this->bih.biWidth,
+ (this->bih.biHeight <= 0) ? 32 : this->bih.biHeight,
this->aspect_ratio,
this->output_format,
- VO_BOTH_FIELDS|this->frame_flags);
+ VO_BOTH_FIELDS|frame_flags_to_use);
/* set PTS to allow early syncing */
img->pts = this->pts;
this->pts = 0;
img->duration = video_step_to_use;
+ /* transfer some more frame settings when running in demux_mpeg_pes context */
+ if (!this->video_step) {
+ img->progressive_frame = !this->av_frame->interlaced_frame;
+ img->top_field_first = this->av_frame->top_field_first;
+ }
img->bad_frame = 1;
this->skipframes = img->draw(img, this->stream);
img->free(img);