mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
mpegvideoparse: Handle Sequence Display Extension
Change the way the pixel-aspect-ratio is computed by interpreting the sequence header aspect ratio info as MPEG-1 values until a sequence extension or sequence display extension is seen, and then updating the sequence header struct accordingly. Fixes incorrect anamorphic display on some MPEG-2 (DVD) sequences.
This commit is contained in:
parent
ad14b96c79
commit
c5c44628fc
4 changed files with 279 additions and 129 deletions
|
@ -107,32 +107,32 @@ failed:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set the Pixel Aspect Ratio in our hdr from a DAR code in the data */
|
||||
/* Set the Pixel Aspect Ratio in our hdr from a ASR code in the data */
|
||||
static void
|
||||
set_par_from_dar (GstMpegVideoSequenceHdr * seqhdr, guint8 asr_code)
|
||||
set_par_from_asr_mpeg1 (GstMpegVideoSequenceHdr * seqhdr, guint8 asr_code)
|
||||
{
|
||||
/* Pixel_width = DAR_width * display_vertical_size */
|
||||
/* Pixel_height = DAR_height * display_horizontal_size */
|
||||
switch (asr_code) {
|
||||
case 0x02: /* 3:4 DAR = 4:3 pixels */
|
||||
seqhdr->par_w = 4 * seqhdr->height;
|
||||
seqhdr->par_h = 3 * seqhdr->width;
|
||||
break;
|
||||
case 0x03: /* 9:16 DAR */
|
||||
seqhdr->par_w = 16 * seqhdr->height;
|
||||
seqhdr->par_h = 9 * seqhdr->width;
|
||||
break;
|
||||
case 0x04: /* 1:2.21 DAR */
|
||||
seqhdr->par_w = 221 * seqhdr->height;
|
||||
seqhdr->par_h = 100 * seqhdr->width;
|
||||
break;
|
||||
case 0x01: /* Square pixels */
|
||||
seqhdr->par_w = seqhdr->par_h = 1;
|
||||
break;
|
||||
default:
|
||||
GST_DEBUG ("unknown/invalid aspect_ratio_information %d", asr_code);
|
||||
break;
|
||||
}
|
||||
int ratios[16][2] = {
|
||||
{0, 0}, /* 0, Invalid */
|
||||
{1, 1}, /* 1, 1.0 */
|
||||
{10000, 6735}, /* 2, 0.6735 */
|
||||
{64, 45}, /* 3, 0.7031 16:9 625 line */
|
||||
{10000, 7615}, /* 4, 0.7615 */
|
||||
{10000, 8055}, /* 5, 0.8055 */
|
||||
{32, 27}, /* 6, 0.8437 */
|
||||
{10000, 8935}, /* 7, 0.8935 */
|
||||
{10000, 9375}, /* 8, 0.9375 */
|
||||
{10000, 9815}, /* 9, 0.9815 */
|
||||
{10000, 10255}, /* 10, 1.0255 */
|
||||
{10000, 10695}, /* 11, 1.0695 */
|
||||
{8, 9}, /* 12, 1.125 */
|
||||
{10000, 11575}, /* 13, 1.1575 */
|
||||
{10000, 12015}, /* 14, 1.2015 */
|
||||
{0, 0}, /* 15, invalid */
|
||||
};
|
||||
asr_code &= 0xf;
|
||||
|
||||
seqhdr->par_w = ratios[asr_code][0];
|
||||
seqhdr->par_h = ratios[asr_code][1];
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -156,79 +156,6 @@ set_fps_from_code (GstMpegVideoSequenceHdr * seqhdr, guint8 fps_code)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mpeg_video_parse_sequence (GstMpegVideoSequenceHdr * seqhdr,
|
||||
GstBitReader * br)
|
||||
{
|
||||
guint8 bits;
|
||||
guint8 load_intra_flag, load_non_intra_flag;
|
||||
|
||||
/* Setting the height/width codes */
|
||||
READ_UINT16 (br, seqhdr->width, 12);
|
||||
READ_UINT16 (br, seqhdr->height, 12);
|
||||
|
||||
READ_UINT8 (br, seqhdr->aspect_ratio_info, 4);
|
||||
set_par_from_dar (seqhdr, seqhdr->aspect_ratio_info);
|
||||
|
||||
READ_UINT8 (br, seqhdr->frame_rate_code, 4);
|
||||
set_fps_from_code (seqhdr, seqhdr->frame_rate_code);
|
||||
|
||||
READ_UINT32 (br, seqhdr->bitrate_value, 18);
|
||||
if (seqhdr->bitrate_value == 0x3ffff) {
|
||||
/* VBR stream */
|
||||
seqhdr->bitrate = 0;
|
||||
} else {
|
||||
/* Value in header is in units of 400 bps */
|
||||
seqhdr->bitrate *= 400;
|
||||
}
|
||||
|
||||
READ_UINT8 (br, bits, 1);
|
||||
if (bits != MARKER_BIT)
|
||||
goto failed;
|
||||
|
||||
/* VBV buffer size */
|
||||
READ_UINT16 (br, seqhdr->vbv_buffer_size_value, 10);
|
||||
|
||||
/* constrained_parameters_flag */
|
||||
READ_UINT8 (br, seqhdr->constrained_parameters_flag, 1);
|
||||
|
||||
/* load_intra_quantiser_matrix */
|
||||
READ_UINT8 (br, load_intra_flag, 1);
|
||||
if (load_intra_flag) {
|
||||
gint i;
|
||||
for (i = 0; i < 64; i++)
|
||||
READ_UINT8 (br, seqhdr->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
|
||||
} else
|
||||
memcpy (seqhdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
|
||||
|
||||
/* non intra quantizer matrix */
|
||||
READ_UINT8 (br, load_non_intra_flag, 1);
|
||||
if (load_non_intra_flag) {
|
||||
gint i;
|
||||
for (i = 0; i < 64; i++)
|
||||
READ_UINT8 (br, seqhdr->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
|
||||
8);
|
||||
} else
|
||||
memset (seqhdr->non_intra_quantizer_matrix, 16, 64);
|
||||
|
||||
/* dump some info */
|
||||
GST_LOG ("width x height: %d x %d", seqhdr->width, seqhdr->height);
|
||||
GST_LOG ("fps: %d/%d", seqhdr->fps_n, seqhdr->fps_d);
|
||||
GST_LOG ("par: %d/%d", seqhdr->par_w, seqhdr->par_h);
|
||||
GST_LOG ("bitrate: %d", seqhdr->bitrate);
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
failed:
|
||||
{
|
||||
GST_WARNING ("Failed to parse sequence header");
|
||||
/* clear out stuff */
|
||||
memset (seqhdr, 0, sizeof (*seqhdr));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* @size and @offset are wrt current reader position */
|
||||
static inline guint
|
||||
scan_for_start_codes (const GstByteReader * reader, guint offset, guint size)
|
||||
|
@ -347,6 +274,8 @@ gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
|
|||
const guint8 * data, gsize size, guint offset)
|
||||
{
|
||||
GstBitReader br;
|
||||
guint8 bits;
|
||||
guint8 load_intra_flag, load_non_intra_flag;
|
||||
|
||||
g_return_val_if_fail (seqhdr != NULL, FALSE);
|
||||
|
||||
|
@ -357,7 +286,72 @@ gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
|
|||
|
||||
gst_bit_reader_init (&br, &data[offset], size);
|
||||
|
||||
return gst_mpeg_video_parse_sequence (seqhdr, &br);
|
||||
/* Setting the height/width codes */
|
||||
READ_UINT16 (&br, seqhdr->width, 12);
|
||||
READ_UINT16 (&br, seqhdr->height, 12);
|
||||
|
||||
READ_UINT8 (&br, seqhdr->aspect_ratio_info, 4);
|
||||
/* Interpret PAR according to MPEG-1. Needs to be reinterpreted
|
||||
* later, if a sequence_display extension is seen */
|
||||
set_par_from_asr_mpeg1 (seqhdr, seqhdr->aspect_ratio_info);
|
||||
|
||||
READ_UINT8 (&br, seqhdr->frame_rate_code, 4);
|
||||
set_fps_from_code (seqhdr, seqhdr->frame_rate_code);
|
||||
|
||||
READ_UINT32 (&br, seqhdr->bitrate_value, 18);
|
||||
if (seqhdr->bitrate_value == 0x3ffff) {
|
||||
/* VBR stream */
|
||||
seqhdr->bitrate = 0;
|
||||
} else {
|
||||
/* Value in header is in units of 400 bps */
|
||||
seqhdr->bitrate *= 400;
|
||||
}
|
||||
|
||||
READ_UINT8 (&br, bits, 1);
|
||||
if (bits != MARKER_BIT)
|
||||
goto failed;
|
||||
|
||||
/* VBV buffer size */
|
||||
READ_UINT16 (&br, seqhdr->vbv_buffer_size_value, 10);
|
||||
|
||||
/* constrained_parameters_flag */
|
||||
READ_UINT8 (&br, seqhdr->constrained_parameters_flag, 1);
|
||||
|
||||
/* load_intra_quantiser_matrix */
|
||||
READ_UINT8 (&br, load_intra_flag, 1);
|
||||
if (load_intra_flag) {
|
||||
gint i;
|
||||
for (i = 0; i < 64; i++)
|
||||
READ_UINT8 (&br, seqhdr->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
|
||||
} else
|
||||
memcpy (seqhdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
|
||||
|
||||
/* non intra quantizer matrix */
|
||||
READ_UINT8 (&br, load_non_intra_flag, 1);
|
||||
if (load_non_intra_flag) {
|
||||
gint i;
|
||||
for (i = 0; i < 64; i++)
|
||||
READ_UINT8 (&br, seqhdr->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
|
||||
8);
|
||||
} else
|
||||
memset (seqhdr->non_intra_quantizer_matrix, 16, 64);
|
||||
|
||||
/* dump some info */
|
||||
GST_LOG ("width x height: %d x %d", seqhdr->width, seqhdr->height);
|
||||
GST_LOG ("fps: %d/%d", seqhdr->fps_n, seqhdr->fps_d);
|
||||
GST_LOG ("par: %d/%d", seqhdr->par_w, seqhdr->par_h);
|
||||
GST_LOG ("bitrate: %d", seqhdr->bitrate);
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
failed:
|
||||
{
|
||||
GST_WARNING ("Failed to parse sequence header");
|
||||
/* clear out stuff */
|
||||
memset (seqhdr, 0, sizeof (*seqhdr));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -426,6 +420,110 @@ gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_mpeg_video_parse_sequence_display_extension (GstMpegVideoSequenceDisplayExt
|
||||
* seqdisplayext, const guint8 * data, gsize size, guint offset)
|
||||
{
|
||||
GstBitReader br;
|
||||
|
||||
g_return_val_if_fail (seqdisplayext != NULL, FALSE);
|
||||
if (offset > size)
|
||||
return FALSE;
|
||||
|
||||
size -= offset;
|
||||
if (size < 5) {
|
||||
GST_DEBUG ("not enough bytes to parse the extension");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_bit_reader_init (&br, &data[offset], size);
|
||||
|
||||
if (gst_bit_reader_get_bits_uint8_unchecked (&br, 4) !=
|
||||
GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY) {
|
||||
GST_DEBUG ("Not parsing a sequence display extension");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
seqdisplayext->video_format =
|
||||
gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
|
||||
seqdisplayext->colour_description_flag =
|
||||
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||
|
||||
if (seqdisplayext->colour_description_flag) {
|
||||
seqdisplayext->colour_primaries =
|
||||
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||
seqdisplayext->transfer_characteristics =
|
||||
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||
seqdisplayext->matrix_coefficients =
|
||||
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||
}
|
||||
|
||||
if (gst_bit_reader_get_remaining (&br) < 29) {
|
||||
GST_DEBUG ("Not enough remaining bytes to parse the extension");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
seqdisplayext->display_horizontal_size =
|
||||
gst_bit_reader_get_bits_uint16_unchecked (&br, 14);
|
||||
/* skip marker bit */
|
||||
gst_bit_reader_skip_unchecked (&br, 1);
|
||||
seqdisplayext->display_vertical_size =
|
||||
gst_bit_reader_get_bits_uint16_unchecked (&br, 14);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_mpeg_video_finalise_mpeg2_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
|
||||
GstMpegVideoSequenceExt * seqext,
|
||||
GstMpegVideoSequenceDisplayExt * displayext)
|
||||
{
|
||||
guint32 w;
|
||||
guint32 h;
|
||||
|
||||
if (seqext) {
|
||||
seqhdr->fps_n = seqhdr->fps_n * (seqext->fps_n_ext + 1);
|
||||
seqhdr->fps_d = seqhdr->fps_d * (seqext->fps_d_ext + 1);
|
||||
/* Extend width and height to 14 bits by adding the extension bits */
|
||||
seqhdr->width |= (seqext->horiz_size_ext << 12);
|
||||
seqhdr->height |= (seqext->vert_size_ext << 12);
|
||||
}
|
||||
|
||||
w = seqhdr->width;
|
||||
h = seqhdr->height;
|
||||
if (displayext) {
|
||||
/* Use the display size for calculating PAR when display ext present */
|
||||
w = displayext->display_horizontal_size;
|
||||
h = displayext->display_vertical_size;
|
||||
}
|
||||
|
||||
/* Pixel_width = DAR_width * display_vertical_size */
|
||||
/* Pixel_height = DAR_height * display_horizontal_size */
|
||||
switch (seqhdr->aspect_ratio_info) {
|
||||
case 0x01: /* Square pixels */
|
||||
seqhdr->par_w = seqhdr->par_h = 1;
|
||||
break;
|
||||
case 0x02: /* 3:4 DAR = 4:3 pixels */
|
||||
seqhdr->par_w = 4 * h;
|
||||
seqhdr->par_h = 3 * w;
|
||||
break;
|
||||
case 0x03: /* 9:16 DAR */
|
||||
seqhdr->par_w = 16 * h;
|
||||
seqhdr->par_h = 9 * w;
|
||||
break;
|
||||
case 0x04: /* 1:2.21 DAR */
|
||||
seqhdr->par_w = 221 * h;
|
||||
seqhdr->par_h = 100 * w;
|
||||
break;
|
||||
default:
|
||||
GST_DEBUG ("unknown/invalid aspect_ratio_information %d",
|
||||
seqhdr->aspect_ratio_info);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpeg_video_parse_quant_matrix_extension:
|
||||
* @quant: (out): The #GstMpegVideoQuantMatrixExt structure to fill
|
||||
|
|
|
@ -175,6 +175,7 @@ typedef enum {
|
|||
|
||||
typedef struct _GstMpegVideoSequenceHdr GstMpegVideoSequenceHdr;
|
||||
typedef struct _GstMpegVideoSequenceExt GstMpegVideoSequenceExt;
|
||||
typedef struct _GstMpegVideoSequenceDisplayExt GstMpegVideoSequenceDisplayExt;
|
||||
typedef struct _GstMpegVideoPictureHdr GstMpegVideoPictureHdr;
|
||||
typedef struct _GstMpegVideoGop GstMpegVideoGop;
|
||||
typedef struct _GstMpegVideoPictureExt GstMpegVideoPictureExt;
|
||||
|
@ -218,16 +219,16 @@ struct _GstMpegVideoSequenceHdr
|
|||
|
||||
/**
|
||||
* GstMpegVideoSequenceExt:
|
||||
* @profile: mpeg2 decoder profil
|
||||
* @profile: mpeg2 decoder profile
|
||||
* @level: mpeg2 decoder level
|
||||
* @progressive: %TRUE if the frames are progressive %FALSE otherwize
|
||||
* @progressive: %TRUE if the frames are progressive %FALSE otherwise
|
||||
* @chroma_format: indicates the chrominance format
|
||||
* @horiz_size_ext: Horizontal size
|
||||
* @vert_size_ext: Vertical size
|
||||
* @bitrate_ext: The bitrate
|
||||
* @vbv_buffer_size_extension: Vbv vuffer size
|
||||
* @vbv_buffer_size_extension: VBV vuffer size
|
||||
* @low_delay: %TRUE if the sequence doesn't contain any B-pictures, %FALSE
|
||||
* otherwize
|
||||
* otherwise
|
||||
* @fps_n_ext: Framerate nominator code
|
||||
* @fps_d_ext: Framerate denominator code
|
||||
*
|
||||
|
@ -252,6 +253,25 @@ struct _GstMpegVideoSequenceExt
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* GstMpegVideoSequenceDisplayExt:
|
||||
* @profile: mpeg2 decoder profil
|
||||
|
||||
*/
|
||||
struct _GstMpegVideoSequenceDisplayExt
|
||||
{
|
||||
guint8 video_format;
|
||||
guint8 colour_description_flag;
|
||||
|
||||
/* if colour_description_flag: */
|
||||
guint8 colour_primaries;
|
||||
guint8 transfer_characteristics;
|
||||
guint8 matrix_coefficients;
|
||||
|
||||
guint16 display_horizontal_size;
|
||||
guint16 display_vertical_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstMpegVideoQuantMatrixExt:
|
||||
* @load_intra_quantiser_matrix:
|
||||
|
@ -384,6 +404,10 @@ gboolean gst_mpeg_video_parse (GstMpegVideoPacket * pack
|
|||
gboolean gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * params,
|
||||
const guint8 * data, gsize size, guint offset);
|
||||
|
||||
/* seqext and displayext may be NULL if not received */
|
||||
gboolean gst_mpeg_video_finalise_mpeg2_sequence_header (GstMpegVideoSequenceHdr *hdr,
|
||||
GstMpegVideoSequenceExt *seqext, GstMpegVideoSequenceDisplayExt *displayext);
|
||||
|
||||
gboolean gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr* hdr,
|
||||
const guint8 * data, gsize size, guint offset);
|
||||
|
||||
|
@ -396,6 +420,9 @@ gboolean gst_mpeg_video_parse_gop (GstMpegVideoGop * gop,
|
|||
gboolean gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
|
||||
const guint8 * data, gsize size, guint offset);
|
||||
|
||||
gboolean gst_mpeg_video_parse_sequence_display_extension (GstMpegVideoSequenceDisplayExt * seqdisplayext,
|
||||
const guint8 * data, gsize size, guint offset);
|
||||
|
||||
gboolean gst_mpeg_video_parse_quant_matrix_extension (GstMpegVideoQuantMatrixExt * quant,
|
||||
const guint8 * data, gsize size, guint offset);
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
|
|||
static void
|
||||
gst_mpegv_parse_init (GstMpegvParse * parse)
|
||||
{
|
||||
parse->mpeg_version = 0;
|
||||
parse->config_flags = FLAG_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -196,6 +196,7 @@ gst_mpegv_parse_reset (GstMpegvParse * mpvparse)
|
|||
gst_buffer_replace (&mpvparse->config, NULL);
|
||||
memset (&mpvparse->sequencehdr, 0, sizeof (mpvparse->sequencehdr));
|
||||
memset (&mpvparse->sequenceext, 0, sizeof (mpvparse->sequenceext));
|
||||
memset (&mpvparse->sequencedispext, 0, sizeof (mpvparse->sequencedispext));
|
||||
memset (&mpvparse->pichdr, 0, sizeof (mpvparse->pichdr));
|
||||
}
|
||||
|
||||
|
@ -232,6 +233,7 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
guint8 *data;
|
||||
guint8 *data_with_prefix;
|
||||
GstMapInfo map;
|
||||
gint i, offset;
|
||||
|
||||
if (mpvparse->seq_offset < 4) {
|
||||
/* This shouldn't happen, but just in case... */
|
||||
|
@ -256,13 +258,8 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (gst_mpeg_video_parse_sequence_header (&mpvparse->sequencehdr, data,
|
||||
if (!gst_mpeg_video_parse_sequence_header (&mpvparse->sequencehdr, data,
|
||||
size - mpvparse->seq_offset, 0)) {
|
||||
if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) {
|
||||
mpvparse->fps_num = mpvparse->sequencehdr.fps_n;
|
||||
mpvparse->fps_den = mpvparse->sequencehdr.fps_d;
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (mpvparse,
|
||||
"failed to parse config data (size %d) at offset %d",
|
||||
size, mpvparse->seq_offset);
|
||||
|
@ -273,23 +270,41 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
|
|||
GST_LOG_OBJECT (mpvparse, "accepting parsed config size %d", size);
|
||||
|
||||
/* Set mpeg version, and parse sequence extension */
|
||||
if (mpvparse->mpeg_version <= 0) {
|
||||
gint i, offset;
|
||||
|
||||
mpvparse->mpeg_version = 1;
|
||||
for (i = 0; i < mpvparse->ext_count; ++i) {
|
||||
offset = mpvparse->ext_offsets[i];
|
||||
mpvparse->mpeg_version = 2;
|
||||
if (offset < size &&
|
||||
gst_mpeg_video_parse_sequence_extension (&mpvparse->sequenceext,
|
||||
mpvparse->config_flags = FLAG_NONE;
|
||||
for (i = 0; i < mpvparse->ext_count; ++i) {
|
||||
offset = mpvparse->ext_offsets[i];
|
||||
mpvparse->config_flags |= FLAG_MPEG2;
|
||||
if (offset < size) {
|
||||
if (gst_mpeg_video_parse_sequence_extension (&mpvparse->sequenceext,
|
||||
map.data, size, offset)) {
|
||||
mpvparse->fps_num =
|
||||
mpvparse->sequencehdr.fps_n * (mpvparse->sequenceext.fps_n_ext + 1);
|
||||
mpvparse->fps_den =
|
||||
mpvparse->sequencehdr.fps_d * (mpvparse->sequenceext.fps_d_ext + 1);
|
||||
GST_LOG_OBJECT (mpvparse, "Read Sequence Extension");
|
||||
mpvparse->config_flags |= FLAG_SEQUENCE_EXT;
|
||||
} else
|
||||
if (gst_mpeg_video_parse_sequence_display_extension
|
||||
(&mpvparse->sequencedispext, map.data, size, offset)) {
|
||||
GST_LOG_OBJECT (mpvparse, "Read Sequence Display Extension");
|
||||
mpvparse->config_flags |= FLAG_SEQUENCE_DISPLAY_EXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mpvparse->config_flags & FLAG_MPEG2) {
|
||||
/* Update the sequence header based on extensions */
|
||||
GstMpegVideoSequenceExt *seqext = NULL;
|
||||
GstMpegVideoSequenceDisplayExt *seqdispext = NULL;
|
||||
|
||||
if (mpvparse->config_flags & FLAG_SEQUENCE_EXT)
|
||||
seqext = &mpvparse->sequenceext;
|
||||
if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT)
|
||||
seqdispext = &mpvparse->sequencedispext;
|
||||
|
||||
gst_mpeg_video_finalise_mpeg2_sequence_header (&mpvparse->sequencehdr,
|
||||
seqext, seqdispext);
|
||||
}
|
||||
|
||||
if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) {
|
||||
mpvparse->fps_num = mpvparse->sequencehdr.fps_n;
|
||||
mpvparse->fps_den = mpvparse->sequencehdr.fps_d;
|
||||
}
|
||||
|
||||
/* parsing ok, so accept it as new config */
|
||||
if (mpvparse->config != NULL)
|
||||
|
@ -627,10 +642,9 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
|
|||
* config data, so we should at least know about version.
|
||||
* If not, it means it has been requested not to drop data, and
|
||||
* upstream and/or app must know what they are doing ... */
|
||||
|
||||
if (G_LIKELY (mpvparse->mpeg_version))
|
||||
gst_caps_set_simple (caps,
|
||||
"mpegversion", G_TYPE_INT, mpvparse->mpeg_version, NULL);
|
||||
gst_caps_set_simple (caps,
|
||||
"mpegversion", G_TYPE_INT, (mpvparse->config_flags & FLAG_MPEG2) ? 2 : 1,
|
||||
NULL);
|
||||
|
||||
gst_caps_set_simple (caps, "systemstream", G_TYPE_BOOLEAN, FALSE,
|
||||
"parsed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
|
@ -664,7 +678,7 @@ gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
|
|||
GST_TYPE_BUFFER, mpvparse->config, NULL);
|
||||
}
|
||||
|
||||
if (mpvparse->mpeg_version == 2) {
|
||||
if (mpvparse->config_flags & FLAG_SEQUENCE_EXT) {
|
||||
const guint profile_c = mpvparse->sequenceext.profile;
|
||||
const guint level_c = mpvparse->sequenceext.level;
|
||||
const gchar *profile = NULL, *level = NULL;
|
||||
|
@ -782,7 +796,9 @@ gst_mpegv_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
gchar *codec;
|
||||
|
||||
/* codec tag */
|
||||
codec = g_strdup_printf ("MPEG %d Video", mpvparse->mpeg_version);
|
||||
codec =
|
||||
g_strdup_printf ("MPEG %d Video",
|
||||
(mpvparse->config_flags & FLAG_MPEG2) ? 2 : 1);
|
||||
taglist = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec, NULL);
|
||||
g_free (codec);
|
||||
|
||||
|
|
|
@ -47,6 +47,14 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstMpegvParse GstMpegvParse;
|
||||
typedef struct _GstMpegvParseClass GstMpegvParseClass;
|
||||
|
||||
/* Config/sequence flags. Reset each time config is re-parsed */
|
||||
enum {
|
||||
FLAG_NONE = 0,
|
||||
FLAG_MPEG2 = 1,
|
||||
FLAG_SEQUENCE_EXT = 2,
|
||||
FLAG_SEQUENCE_DISPLAY_EXT = 4
|
||||
};
|
||||
|
||||
struct _GstMpegvParse {
|
||||
GstBaseParse element;
|
||||
|
||||
|
@ -62,9 +70,10 @@ struct _GstMpegvParse {
|
|||
|
||||
GstBuffer *config;
|
||||
guint8 profile;
|
||||
guint mpeg_version;
|
||||
guint config_flags;
|
||||
GstMpegVideoSequenceHdr sequencehdr;
|
||||
GstMpegVideoSequenceExt sequenceext;
|
||||
GstMpegVideoSequenceDisplayExt sequencedispext;
|
||||
GstMpegVideoPictureHdr pichdr;
|
||||
|
||||
/* properties */
|
||||
|
|
Loading…
Reference in a new issue