mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 17:32:06 +00:00
Add jpeg2000 subdescriptor (V2).
Signed-off-by: Cedric Le Barz <clebarz@ektacom.com>
This commit is contained in:
parent
e063c1d079
commit
238f9de876
@ -55,6 +55,7 @@ enum MXFMetadataSetType {
|
||||
SoundfieldGroupLabelSubDescriptor,
|
||||
GroupOfSoundfieldGroupsLabelSubDescriptor,
|
||||
FFV1SubDescriptor,
|
||||
JPEG2000SubDescriptor,
|
||||
};
|
||||
|
||||
enum MXFFrameLayout {
|
||||
|
@ -48,8 +48,10 @@
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/time_internal.h"
|
||||
#include "libavcodec/defs.h"
|
||||
#include "libavcodec/bytestream.h"
|
||||
#include "libavcodec/golomb.h"
|
||||
#include "libavcodec/h264.h"
|
||||
#include "libavcodec/jpeg2000.h"
|
||||
#include "libavcodec/packet_internal.h"
|
||||
#include "libavcodec/rangecoder.h"
|
||||
#include "libavcodec/startcode.h"
|
||||
@ -78,6 +80,20 @@ typedef struct MXFIndexEntry {
|
||||
uint8_t flags;
|
||||
} MXFIndexEntry;
|
||||
|
||||
typedef struct j2k_info_t {
|
||||
uint16_t j2k_cap; ///< j2k required decoder capabilities
|
||||
uint16_t j2k_rsiz; ///< j2k required decoder capabilities (Rsiz)
|
||||
uint32_t j2k_xsiz; ///< j2k width of the reference grid (Xsiz)
|
||||
uint32_t j2k_ysiz; ///< j2k height of the reference grid (Ysiz)
|
||||
uint32_t j2k_x0siz; ///< j2k horizontal offset from the origin of the reference grid to the left side of the image (X0siz)
|
||||
uint32_t j2k_y0siz; ///< j2k vertical offset from the origin of the reference grid to the left side of the image (Y0siz)
|
||||
uint32_t j2k_xtsiz; ///< j2k width of one reference tile with respect to the reference grid (XTsiz)
|
||||
uint32_t j2k_ytsiz; ///< j2k height of one reference tile with respect to the reference grid (YTsiz)
|
||||
uint32_t j2k_xt0siz; ///< j2k horizontal offset from the origin of the reference grid to the left side of the first tile (XT0siz)
|
||||
uint32_t j2k_yt0siz; ///< j2k vertical offset from the origin of the reference grid to the left side of the first tile (YT0siz)
|
||||
uint8_t j2k_comp_desc[12]; ///< j2k components descriptor (Ssiz(i), XRsiz(i), YRsiz(i))
|
||||
} j2k_info_t;
|
||||
|
||||
typedef struct MXFStreamContext {
|
||||
int64_t pkt_cnt; ///< pkt counter for muxed packets
|
||||
UID track_essence_element_key;
|
||||
@ -104,6 +120,7 @@ typedef struct MXFStreamContext {
|
||||
int low_delay; ///< low delay, used in mpeg-2 descriptor
|
||||
int avc_intra;
|
||||
int micro_version; ///< format micro_version, used in ffv1 descriptor
|
||||
j2k_info_t j2k_info;
|
||||
} MXFStreamContext;
|
||||
|
||||
typedef struct MXFContainerEssenceEntry {
|
||||
@ -413,6 +430,20 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
|
||||
{ 0xDFD9, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x06,0x00,0x00,0x00}}, /* FFV1 Micro-version */
|
||||
{ 0xDFDA, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x05,0x00,0x00,0x00}}, /* FFV1 Version */
|
||||
{ 0xDFDB, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x0C,0x01,0x00,0x00,0x00}}, /* FFV1 Initialization Metadata */
|
||||
// ff_mxf_jpeg2000_local_tags
|
||||
{ 0x8400, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}}, /* Sub Descriptors / Opt Ordered array of strong references to sub descriptor sets */
|
||||
{ 0x8401, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x01,0x00,0x00,0x00}}, /* Rsiz: An enumerated value that defines the decoder capabilities */
|
||||
{ 0x8402, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x02,0x00,0x00,0x00}}, /* Xsiz: Width of the reference grid */
|
||||
{ 0x8403, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x03,0x00,0x00,0x00}}, /* Ysiz: Height of the reference grid */
|
||||
{ 0x8404, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x04,0x00,0x00,0x00}}, /* X0siz: Horizontal offset from the origin of the reference grid to the left side of the image area */
|
||||
{ 0x8405, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x05,0x00,0x00,0x00}}, /* Y0siz: Vertical offset from the origin of the reference grid to the left side of the image area */
|
||||
{ 0x8406, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x06,0x00,0x00,0x00}}, /* XTsiz: Width of one reference tile with respect to the reference grid */
|
||||
{ 0x8407, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x07,0x00,0x00,0x00}}, /* YTsiz: Height of one reference tile with respect to the reference grid */
|
||||
{ 0x8408, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x08,0x00,0x00,0x00}}, /* XT0siz: Horizontal offset from the origin of the reference grid to the left side of the first tile */
|
||||
{ 0x8409, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x09,0x00,0x00,0x00}}, /* YT0siz: Vertical offset from the origin of the reference grid to the left side of the first tile */
|
||||
{ 0x840A, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x0A,0x00,0x00,0x00}}, /* Csiz: The number of components in the picture */
|
||||
{ 0x840B, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x0B,0x00,0x00,0x00}}, /* Ssizi, XRSizi, YRSizi: Array of picture components where each component comprises 3 bytes named Ssizi, XRSizi, YRSizi. The array of 3-byte groups is preceded by the array header comprising a 4-byte value of the number of components followed by a 4-byte value of 3. */
|
||||
{ 0x840C, {0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x0E,0x00,0x00,0x00}}, /* The nature and order of the image components in the compressed domain as carried in the J2C codestream. */
|
||||
};
|
||||
|
||||
#define MXF_NUM_TAGS FF_ARRAY_ELEMS(mxf_local_tag_batch)
|
||||
@ -549,7 +580,7 @@ static void mxf_write_primer_pack(AVFormatContext *s)
|
||||
MXFContext *mxf = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
int local_tag_number = MXF_NUM_TAGS, i;
|
||||
int will_have_avc_tags = 0, will_have_mastering_tags = 0, will_have_ffv1_tags = 0;
|
||||
int will_have_avc_tags = 0, will_have_mastering_tags = 0, will_have_ffv1_tags = 0, will_have_jpeg2000_tags = 0;
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
MXFStreamContext *sc = s->streams[i]->priv_data;
|
||||
@ -564,6 +595,9 @@ static void mxf_write_primer_pack(AVFormatContext *s)
|
||||
if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_FFV1) {
|
||||
will_have_ffv1_tags = 1;
|
||||
}
|
||||
if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_JPEG2000){
|
||||
will_have_jpeg2000_tags = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mxf->store_user_comments) {
|
||||
@ -595,6 +629,22 @@ static void mxf_write_primer_pack(AVFormatContext *s)
|
||||
mxf_mark_tag_unused(mxf, 0xDFDB);
|
||||
}
|
||||
|
||||
if (!will_have_jpeg2000_tags) {
|
||||
mxf_mark_tag_unused(mxf, 0x8400);
|
||||
mxf_mark_tag_unused(mxf, 0x8401);
|
||||
mxf_mark_tag_unused(mxf, 0x8402);
|
||||
mxf_mark_tag_unused(mxf, 0x8403);
|
||||
mxf_mark_tag_unused(mxf, 0x8404);
|
||||
mxf_mark_tag_unused(mxf, 0x8405);
|
||||
mxf_mark_tag_unused(mxf, 0x8406);
|
||||
mxf_mark_tag_unused(mxf, 0x8407);
|
||||
mxf_mark_tag_unused(mxf, 0x8408);
|
||||
mxf_mark_tag_unused(mxf, 0x8409);
|
||||
mxf_mark_tag_unused(mxf, 0x840A);
|
||||
mxf_mark_tag_unused(mxf, 0x840B);
|
||||
mxf_mark_tag_unused(mxf, 0x840C);
|
||||
}
|
||||
|
||||
for (i = 0; i < MXF_NUM_TAGS; i++) {
|
||||
if (mxf->unused_tags[i]) {
|
||||
local_tag_number--;
|
||||
@ -1136,6 +1186,7 @@ static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0
|
||||
|
||||
static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 };
|
||||
static const UID mxf_ffv1_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x03 };
|
||||
static const UID mxf_jpeg2000_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x5A,0x00};
|
||||
|
||||
static inline uint16_t rescale_mastering_chroma(AVRational q)
|
||||
{
|
||||
@ -1430,6 +1481,64 @@ static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st)
|
||||
mxf_update_klv_size(s->pb, pos);
|
||||
}
|
||||
|
||||
static void mxf_write_jpeg2000_subdesc(AVFormatContext *s, AVStream *st)
|
||||
{
|
||||
MXFStreamContext *sc = st->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
int64_t pos;
|
||||
int component_count = av_pix_fmt_count_planes(st->codecpar->format);
|
||||
int comp = 0;
|
||||
|
||||
/* JPEG2000 subdescriptor key */
|
||||
avio_write(pb, mxf_jpeg2000_subdescriptor_key, 16);
|
||||
klv_encode_ber4_length(pb, 0);
|
||||
pos = avio_tell(pb);
|
||||
|
||||
mxf_write_local_tag(s, 16, 0x3C0A);
|
||||
mxf_write_uuid(pb, JPEG2000SubDescriptor, 0);
|
||||
|
||||
/* Value defining the decoder capabilities (rsiz) */
|
||||
mxf_write_local_tag(s, 2, 0x8401);
|
||||
avio_wb16(pb, sc->j2k_info.j2k_rsiz);
|
||||
/* Width of the JPEG2000 reference grid (Xsiz) */
|
||||
mxf_write_local_tag(s, 4, 0x8402);
|
||||
avio_wb32(pb, st->codecpar->width);
|
||||
/* Height of the JPEG2000 reference grid (Ysiz) */
|
||||
mxf_write_local_tag(s, 4, 0x8403);
|
||||
avio_wb32(pb, st->codecpar->height);
|
||||
/* Horizontal offset from the reference grid origin to the left side of the image area (X0siz) */
|
||||
mxf_write_local_tag(s, 4, 0x8404);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_x0siz);
|
||||
/* Vertical offset from the reference grid origin to the left side of the image area (Y0siz) */
|
||||
mxf_write_local_tag(s, 4, 0x8405);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_y0siz);
|
||||
/* Width of one reference tile with respect to the reference grid (XTsiz) */
|
||||
mxf_write_local_tag(s, 4, 0x8406);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_xtsiz);
|
||||
/* Height of one reference tile with respect to the reference grid (YTsiz) */
|
||||
mxf_write_local_tag(s, 4, 0x8407);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_ytsiz);
|
||||
/* Horizontal offset from the origin of the reference grid to the left side of the first tile (XT0siz) */
|
||||
mxf_write_local_tag(s, 4, 0x8408);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_xt0siz);
|
||||
/* Vertical offset from the origin of the reference grid to the left side of the first tile (YT0siz) */
|
||||
mxf_write_local_tag(s, 4, 0x8409);
|
||||
avio_wb32(pb, sc->j2k_info.j2k_yt0siz);
|
||||
/* Image components number (Csiz) */
|
||||
mxf_write_local_tag(s, 2, 0x840A);
|
||||
avio_wb16(pb, component_count);
|
||||
/* Array of picture components where each component comprises 3 bytes named Ssiz(i) (Pixel bitdepth - 1),
|
||||
XRSiz(i) (Horizontal sampling), YRSiz(i) (Vertical sampling). The array of 3-byte groups is preceded
|
||||
by the array header comprising a 4-byte value of the number of components followed by a 4-byte
|
||||
value of 3. */
|
||||
mxf_write_local_tag(s, 8 + 3*component_count, 0x840B);
|
||||
avio_wb32(pb, component_count);
|
||||
avio_wb32(pb, 3);
|
||||
avio_write(pb, sc->j2k_info.j2k_comp_desc, 3*component_count);
|
||||
|
||||
mxf_update_klv_size(pb, pos);
|
||||
}
|
||||
|
||||
static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
|
||||
{
|
||||
int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
|
||||
@ -1438,6 +1547,9 @@ static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
|
||||
mxf_write_avc_subdesc(s, st);
|
||||
}
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_JPEG2000) {
|
||||
mxf_write_jpeg2000_subdesc(s, st);
|
||||
}
|
||||
}
|
||||
|
||||
static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st)
|
||||
@ -2524,6 +2636,56 @@ static int mxf_parse_ffv1_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mxf_parse_jpeg2000_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
||||
{
|
||||
MXFContext *mxf = s->priv_data;
|
||||
MXFStreamContext *sc = st->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
int component_count = av_pix_fmt_count_planes(st->codecpar->format);
|
||||
GetByteContext g;
|
||||
uint32_t j2k_ncomponents;
|
||||
int comp;
|
||||
|
||||
if (mxf->header_written)
|
||||
return 1;
|
||||
|
||||
bytestream2_init(&g,pkt->data,pkt->size);
|
||||
|
||||
while (bytestream2_get_bytes_left(&g) >= 3 && bytestream2_peek_be16(&g) != JPEG2000_SOC)
|
||||
bytestream2_skip(&g, 1);
|
||||
|
||||
if (bytestream2_get_be16u(&g) != JPEG2000_SOC) {
|
||||
av_log(s, AV_LOG_ERROR, "Mandatory SOC marker is not present\n");
|
||||
return AVERROR(AVERROR_INVALIDDATA);
|
||||
}
|
||||
|
||||
/* Extract usefull size information from the SIZ marker */
|
||||
if (bytestream2_get_be16u(&g) != JPEG2000_SIZ) {
|
||||
av_log(s, AV_LOG_ERROR, "Mandatory SIZ marker is not present\n");
|
||||
return AVERROR(AVERROR_INVALIDDATA);
|
||||
}
|
||||
bytestream2_skip(&g, 2); // Skip Lsiz
|
||||
sc->j2k_info.j2k_cap = bytestream2_get_be16u(&g);
|
||||
sc->j2k_info.j2k_xsiz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_ysiz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_x0siz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_y0siz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_xtsiz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_ytsiz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_xt0siz = bytestream2_get_be32u(&g);
|
||||
sc->j2k_info.j2k_yt0siz = bytestream2_get_be32u(&g);
|
||||
j2k_ncomponents = bytestream2_get_be16u(&g);
|
||||
if (j2k_ncomponents != component_count) {
|
||||
av_log(s, AV_LOG_ERROR, "Incoherence about components image number.\n");
|
||||
return AVERROR(AVERROR_INVALIDDATA);
|
||||
}
|
||||
bytestream2_get_bufferu(&g, sc->j2k_info.j2k_comp_desc, 3 * j2k_ncomponents);
|
||||
|
||||
sc->frame_size = pkt->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const UID mxf_mpeg2_codec_uls[] = {
|
||||
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame
|
||||
{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP
|
||||
@ -3140,6 +3302,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
av_log(s, AV_LOG_ERROR, "could not get ffv1 version\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_JPEG2000) {
|
||||
if (!mxf_parse_jpeg2000_frame(s, st, pkt)) {
|
||||
av_log(s, AV_LOG_ERROR, "could not get jpeg2000 profile\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mxf->cbr_index) {
|
||||
|
Loading…
Reference in New Issue
Block a user