[FFmpeg-devel] [Patch/RFC] Improved PixelLayout parsing in mxfdec.c
Baptiste Coudurier
baptiste.coudurier
Fri Jun 4 00:11:10 CEST 2010
Hi,
On 06/03/2010 06:52 AM, Tomas H?rdin wrote:
> Hi
>
> While poking around with transcoding DPX sequences to rawvideo in MXF I
> discovered that the demuxer's handling of the PixelLayout item only
> parses enough to fill in bits_per_coded_sample. The attached patch
> improves the code so that it also figures out pix_fmt. At the moment it
> detects RGB24, RGB48LE/BE and BGR24. More formats are easily added. I
> use pix_fmt to fill in codec_tag using avcodec_pix_fmt_to_codec_tag(),
> since that seemed the most correct way.
No, codec_tag for mxf is not set, or should be set to the container_ul
if there was enough space.
> The code could be shared with the muxer in order to enable rawvideo
> muxing. In that case the code would probably go in mxf.c instead.
That would be welcome.
> Finally, I left the old switch code intact so that YUV formats still
> produce the same value for bits_per_coded_sample.
>
> RFC part follows:
>
> Notice that I have several definitions for PIX_FMT_RGB48BE. This is due
> to some confusion on my part. The reason is that E.2.46 appears to be a
> little ambiguous regarding endianness. The standard provides these two
> examples:
>
> "Example: Component 4:2:2:4
> 8-bit components packed into a 32-bit word, in 601 sequence: Cb Y Cr,
> with alpha in 4th byte of the stored pixel
> PixelLayout = {'U',8,'Y',8,'V',8,'A',8,0,0}"
>
> and
>
> "Example: one of the formats supported by SMPTE 268M
> 10-bit components filled to 32-bit word boundaries, padded in most
> significant bits
> PixelLayout = {'F',2,'B',10,'G',10,'R',10,0,0}"
>
> The first example states that the output bytes come in the same order as
> they are defined in PixelLayout. The second example states that the
> leftmost bytes are the most significant. My interpretation of this is
> that rawvideo must be stored in big-endian form unless otherwise stated
> in PixelLayout (using 'R' and 'r' etc. for MSBs and LSBs). A less
> ambiguous definition of the second example would therefore be:
>
> PixelLayout = {'F',2,'B',6,'b',4,'G',4,'g',6,'R',2,'r',8,0,0}
>
> while the little-endian form would be
>
> PixelLayout = {'r',8,'g',6,'R',2,'b',4,'G',4,'F',2,'B',6,0,0}
>
> That should hopefully make sense. Any thoughts?
I'm not sure. Do you have any file ? No file -> don't need to have that
case yet.
>
> diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
> index 168fd8d..d31c3d3 100644
> --- a/libavformat/mxfdec.c
> +++ b/libavformat/mxfdec.c
> @@ -101,6 +101,7 @@ typedef struct {
> int linked_track_id;
> uint8_t *extradata;
> int extradata_size;
> + enum PixelFormat pix_fmt;
> } MXFDescriptor;
>
> typedef struct {
> @@ -518,27 +519,66 @@ static int mxf_read_index_table_segment(MXFIndexTableSegment *segment, ByteIOCon
> return 0;
> }
>
> +static const struct {
> + enum PixelFormat pix_fmt;
> + int length;
> + int bits_per_sample;
> + const char pixel_layout[16];
You don't need length, use terminating 0.
> [...]
>
> +const int num_pixel_layouts = sizeof(pixel_layouts) / sizeof(*pixel_layouts);
> +
> static void mxf_read_pixel_layout(ByteIOContext *pb, MXFDescriptor *descriptor)
> {
> - int code;
> + int code, value, x, ofs = 0;
> + int64_t pix_fmt_mask = (1LL<< num_pixel_layouts) - 1;
>
> do {
> code = get_byte(pb);
> + value = get_byte(pb);
> dprintf(NULL, "pixel layout: code %#x\n", code);
> switch (code) {
> case 0x52: /* R */
> - descriptor->bits_per_sample += get_byte(pb);
> + descriptor->bits_per_sample += value;
> break;
> case 0x47: /* G */
> - descriptor->bits_per_sample += get_byte(pb);
> + descriptor->bits_per_sample += value;
> break;
> case 0x42: /* B */
> - descriptor->bits_per_sample += get_byte(pb);
> + descriptor->bits_per_sample += value;
> break;
> default:
> - get_byte(pb);
> + break;
> + }
> +
> + if (code) {
> + /* untick layouts that are too short or that don't match */
> + for(x = 0; x< num_pixel_layouts; x++) {
> + if (pixel_layouts[x].length< ofs ||
> + pixel_layouts[x].pixel_layout[ofs] != code ||
> + pixel_layouts[x].pixel_layout[ofs+1] != value)
> + pix_fmt_mask&= ~(1<< x);
> + }
Read the full pixel layout and compare it once.
> [...]
>
> static int mxf_read_generic_descriptor(MXFDescriptor *descriptor, ByteIOContext *pb, int tag, int size, UID uid)
> @@ -802,6 +842,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
> st->codec->width = descriptor->width;
> st->codec->height = descriptor->height;
> st->codec->bits_per_coded_sample = descriptor->bits_per_sample; /* Uncompressed */
> + st->codec->pix_fmt = descriptor->pix_fmt;
> + st->codec->codec_tag = avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
Do not set codec tag.
Thanks for the patch, this is appreciated.
[...]
--
Baptiste COUDURIER
Key fingerprint 8D77134D20CC9220201FC5DB0AC9325C5C1ABAAA
FFmpeg maintainer http://www.ffmpeg.org
More information about the ffmpeg-devel
mailing list