[FFmpeg-soc] [soc]: r373 - dirac/dirac.c
marco
subversion at mplayerhq.hu
Wed Jul 11 10:48:19 CEST 2007
Author: marco
Date: Wed Jul 11 10:48:19 2007
New Revision: 373
Log:
Partial implementation of coefficient unpacking, still contains many hacks.
Modified:
dirac/dirac.c
Modified: dirac/dirac.c
==============================================================================
--- dirac/dirac.c (original)
+++ dirac/dirac.c Wed Jul 11 10:48:19 2007
@@ -194,7 +194,7 @@ static const int preset_chroma_excursion
static const int preset_primaries[4] = { 0, 1, 2, 3 };
static const int preset_matrix[4] = {0, 1, 1, 2 };
-static const transfer_func_t preset_transfer_func[4] =
+static const transfer_func_t preset_transfer_func[3] =
{
TRANSFER_FUNC_TV, TRANSFER_FUNC_TV, TRANSFER_FUNC_DCI_GAMMA
};
@@ -207,12 +207,17 @@ typedef struct DiracContext {
unsigned int profile;
unsigned int level;
+ GetBitContext *gb;
+
struct source_parameters source;
struct sequence_parameters sequence;
struct decoding_parameters decoding;
int codeblocksh[7]; /* XXX: 7 levels. */
int codeblocksv[7]; /* XXX: 7 levels. */
+
+ int padded_width;
+ int padded_height;
} DiracContext;
static int decode_init(AVCodecContext *avctx){
@@ -230,10 +235,10 @@ static int decode_end(AVCodecContext *av
typedef enum {
pc_access_unit_header = 0x00,
- pc_eos = 0x10,
- pc_aux_data = 0x20,
- pc_padding = 0x60,
- pc_intra_ref = 0x0c
+ pc_eos = 0x10,
+ pc_aux_data = 0x20,
+ pc_padding = 0x60,
+ pc_intra_ref = 0x0c
} parse_code_t;
typedef enum {
@@ -254,58 +259,32 @@ static int dirac_golomb(GetBitContext *g
return val;
}
-static int parse_access_unit_header (AVCodecContext *avctx, GetBitContext *gb) {
- DiracContext *s = avctx->priv_data;
- uint32_t version_major;
- uint32_t version_minor;
- uint32_t video_format;
- /* Parse parameters. */
- s->next_picture = get_bits_long(gb, 32);
-
- version_major = dirac_golomb(gb);
- version_minor = dirac_golomb(gb);
- /* XXX: Don't check the version yet, existing encoders do not yet
- set this to a sane value (0.6 at the moment). */
-
- /* XXX: Not yet documented in the spec. This is actually the main
- thing that is missing. */
- s->profile = dirac_golomb(gb);
- s->level = dirac_golomb(gb);
-
- dprintf (avctx, "Access unit header: Version %d.%d\n",
- version_major, version_minor);
- dprintf (avctx, "Profile: %d, Level: %d\n", s->profile, s->level);
-
- /* Sequence parameters. */
- video_format = dirac_golomb(gb);
- dprintf (avctx, "Video format: %d\n", video_format);
-
- /* Fill in defaults for the source parameters. */
- memcpy(&s->source, &source_parameters_defaults[video_format],
- sizeof(s->source));
-
- /* Fill in defaults for the sequence parameters. */
- memcpy(&s->sequence, &sequence_parameters_defaults[video_format],
- sizeof(s->sequence));
+static int dirac_golomb_sign(GetBitContext *gb) {
+ int val = dirac_golomb(gb);
+ if (val)
+ if (get_bits(gb, 1))
+ val = -val;
+ return val;
+}
- /* Fill in defaults for the decoding parameters. */
- memcpy(&s->decoding, &decoding_parameters_defaults[video_format],
- sizeof(s->decoding));
+static void parse_sequence_parameters(AVCodecContext *avctx) {
+ DiracContext *s = avctx->priv_data;
+ GetBitContext *gb = s->gb;
- /* Set custom dimensions. */
+ /* Override the luma dimensions. */
if (get_bits(gb, 1)) {
s->sequence.luma_width = dirac_golomb(gb);
s->sequence.luma_height = dirac_golomb(gb);
}
- /* Set chroma format. */
+ /* Override the chroma format. */
if (get_bits(gb, 1)) {
s->sequence.chroma_format = dirac_golomb(gb);
dprintf (avctx, "Chroma index: %d\n", s->sequence.chroma_format);
}
- /* Set the chroma dimensions. */
+ /* Override the chroma dimensions. */
switch (s->sequence.chroma_format) {
case 0:
/* 4:4:4 */
@@ -333,6 +312,12 @@ static int parse_access_unit_header (AVC
}
dprintf(avctx, "Video mode: %dx%d@%d\n", s->sequence.luma_width, s->sequence.luma_height, s->sequence.video_depth);
+}
+
+
+static void parse_source_parameters(AVCodecContext *avctx) {
+ DiracContext *s = avctx->priv_data;
+ GetBitContext *gb = s->gb;
/* Access Unit Source parameters. */
if (get_bits(gb, 1)) {
@@ -451,6 +436,53 @@ static int parse_access_unit_header (AVC
dprintf (avctx, "Color spec idx: %d\n", idx);
}
+}
+
+
+
+static int parse_access_unit_header(AVCodecContext *avctx) {
+ DiracContext *s = avctx->priv_data;
+ GetBitContext *gb = s->gb;
+ unsigned int version_major;
+ unsigned int version_minor;
+ unsigned int video_format;
+
+ /* Parse parameters. */
+ s->next_picture = get_bits_long(gb, 32);
+
+ version_major = dirac_golomb(gb);
+ version_minor = dirac_golomb(gb);
+ /* XXX: Don't check the version yet, existing encoders do not yet
+ set this to a sane value (0.6 at the moment). */
+
+ /* XXX: Not yet documented in the spec. This is actually the main
+ thing that is missing. */
+ s->profile = dirac_golomb(gb);
+ s->level = dirac_golomb(gb);
+
+ dprintf (avctx, "Access unit header: Version %d.%d\n",
+ version_major, version_minor);
+ dprintf (avctx, "Profile: %d, Level: %d\n", s->profile, s->level);
+
+ video_format = dirac_golomb(gb);
+ dprintf (avctx, "Video format: %d\n", video_format);
+
+ /* Fill in defaults for the sequence parameters. */
+ memcpy(&s->sequence, &sequence_parameters_defaults[video_format],
+ sizeof(s->sequence));
+ /* Override the defaults. */
+ parse_sequence_parameters(avctx);
+
+ /* Fill in defaults for the source parameters. */
+ memcpy(&s->source, &source_parameters_defaults[video_format],
+ sizeof(s->source));
+ /* Override the defaults. */
+ parse_source_parameters(avctx);
+
+ /* Fill in defaults for the decoding parameters. */
+ memcpy(&s->decoding, &decoding_parameters_defaults[video_format],
+ sizeof(s->decoding));
+
dprintf (avctx, "Header read!\n");
return 0;
@@ -518,6 +550,7 @@ static arith_context_t arith_contexts[AR
static void arith_init (GetBitContext *gb, int length) {
int i;
+ align_get_bits(gb);
arith_bits_left = 8 * length;
arith_low = 0;
arith_range = 0x10000;
@@ -546,17 +579,17 @@ static void arith_renormalize (GetBitCon
}
static int arith_lookup[256] = {
- 0, 2, 5, 8, 11, 15, 20, 24,
- 29, 35, 41, 47, 53, 60, 67, 74,
- 82, 89, 97, 106, 114, 123, 132, 141,
- 150, 160, 170, 180, 190, 201, 211, 222,
- 233, 244, 256, 267, 279, 291, 303, 315,
- 327, 340, 353, 366, 379, 392, 405, 419,
- 433, 447, 461, 475, 489, 504, 518, 533,
- 548, 563, 578, 593, 609, 624, 640, 656,
- 672, 688, 705, 721, 738, 754, 771, 788,
- 805, 822, 840, 857, 875, 892, 910, 928,
- 946, 964, 983, 1001, 1020, 1038, 1057, 1076,
+ 0, 2, 5, 8, 11, 15, 20, 24,
+ 29, 35, 41, 47, 53, 60, 67, 74,
+ 82, 89, 97, 106, 114, 123, 132, 141,
+ 150, 160, 170, 180, 190, 201, 211, 222,
+ 233, 244, 256, 267, 279, 291, 303, 315,
+ 327, 340, 353, 366, 379, 392, 405, 419,
+ 433, 447, 461, 475, 489, 504, 518, 533,
+ 548, 563, 578, 593, 609, 624, 640, 656,
+ 672, 688, 705, 721, 738, 754, 771, 788,
+ 805, 822, 840, 857, 875, 892, 910, 928,
+ 946, 964, 983, 1001, 1020, 1038, 1057, 1076,
1095, 1114, 1133, 1153, 1172, 1192, 1211, 1231,
1251, 1271, 1291, 1311, 1332, 1352, 1373, 1393,
1414, 1435, 1456, 1477, 1498, 1520, 1541, 1562,
@@ -576,8 +609,8 @@ static int arith_lookup[256] = {
1727, 1710, 1694, 1676, 1659, 1640, 1622, 1602,
1582, 1561, 1540, 1518, 1495, 1471, 1447, 1422,
1396, 1369, 1341, 1312, 1282, 1251, 1219, 1186,
- 1151, 1114, 1077, 1037, 995, 952, 906, 857,
- 805, 750, 690, 625, 553, 471, 376, 255
+ 1151, 1114, 1077, 1037, 995, 952, 906, 857,
+ 805, 750, 690, 625, 553, 471, 376, 255
};
static int arith_get_bit (GetBitContext *gb, int context) {
@@ -755,15 +788,136 @@ static void arith_flush(GetBitContext *g
arith_bits_left = 0;
}
-static void codeblock (AVCodecContext *avctx, GetBitContext *gb, int level, int x, int y) {
+static int inline subband_width(int width, int level) {
+ int sbwidth = (width + (1 << level) - 1) >> level;
+ if (level == 0)
+ return sbwidth;
+ return sbwidth >> (level - 1);
+}
+
+static int inline subband_height(int height, int level) {
+ int sbheight = (height + (1 << level) - 1) >> level;
+ if (level == 0)
+ return sbheight;
+ return sbheight >> (level - 1);
+}
+
+static int inline coeff_posx(AVCodecContext *avctx, int level,
+ subband_t orientation, int x) {
+ DiracContext *s = avctx->priv_data;
+
+ int right = 0;
+ if (orientation == subband_hl || orientation == subband_hh)
+ right = 1;
+
+ return right * subband_width(s->padded_width, level) + x;
+}
+
+static int inline coeff_posy(AVCodecContext *avctx, int level,
+ subband_t orientation, int y) {
DiracContext *s = avctx->priv_data;
+
+ int bottom = 0;
+ if (orientation == subband_lh || orientation == subband_hh)
+ bottom = 1;
+
+ return bottom * subband_height(s->padded_height, level) + y;
+}
+
+static int zero_neighbourhood(AVCodecContext *avctx, int *data, int level,
+ subband_t orientation, int v, int h) {
+ int x = coeff_posx(avctx, level, orientation, v);
+ int y = coeff_posy(avctx, level, orientation, h);
+ DiracContext *s = avctx->priv_data;
+
+ /* Check if there is a zero to the left and top left of this
+ coefficient. */
+ if (v > 0 && (data[x + y * s->padded_width - 1]
+ || ( h > 0 && data[x + (y - 1) * s->padded_width - 1])))
+ return 0;
+ else if (h > 0 && data[x + (y - 1) * s->padded_width])
+ return 0;
+ /* XXX: The behavior above is used in the standard, but seems a
+ bit broken to me. Either I am wrong or I am, double check! */
+ return 1;
+}
+
+static int sign_predict(AVCodecContext *avctx, int *data, int level,
+ subband_t orientation, int v, int h) {
+ int x = coeff_posx(avctx, level - 1, orientation, v >> 1);
+ int y = coeff_posy(avctx, level - 1, orientation, h >> 1);
+ DiracContext *s = avctx->priv_data;
+
+ switch (orientation) {
+ case subband_ll:
+ case subband_hh:
+ return 0;
+ case subband_hl:
+ if (v == 0)
+ return 0;
+ else
+ return (data[x + (y - 1) * s->padded_width] < 0) ? -1 : 1;
+ case subband_lh:
+ if (h == 0)
+ return 0;
+ else
+ return (data[x + y * s->padded_width - 1] < 0) ? -1 : 1;
+ }
+
+ return 0;
+}
+
+static void coeff_unpack(AVCodecContext *avctx, int *data, int level,
+ subband_t orientation, int v, int h) {
+ int parent = 0;
+ int nhood;
+ int sign_pred;
+ int idx;
+ int coeff;
+ struct context_set *context;
+ DiracContext *s = avctx->priv_data;
+ int vdata, hdata;
+
+ /* The value of the pixel belonging to the lower level. */
+ if (level >= 2) {
+ int x = coeff_posx(avctx, level - 1, orientation, v >> 1);
+ int y = coeff_posy(avctx, level - 1, orientation, h >> 1);
+ parent = data[s->padded_width * y + x];
+ }
+
+ /* Determine if the pixel has a zero in its neighbourhood. */
+ nhood = zero_neighbourhood(avctx, data, level, orientation, v, h);
+
+ sign_pred = sign_predict(avctx, data, level, orientation, v, h);
+
+ /* Calculate an index into context_sets_waveletcoeff. */
+ idx = parent * 6 + (!nhood) * 3;
+ if (sign_pred == -1)
+ idx += 1;
+ else if (sign_pred == 1)
+ idx += 2;
+
+ context = &context_sets_waveletcoeff[idx];
+
+ coeff = arith_read_int(s->gb, context);
+ vdata = coeff_posx(avctx, level, orientation, v);
+ hdata = coeff_posy(avctx, level, orientation, h);
+ data[hdata + vdata * s->padded_width] = coeff;
+}
+
+static void codeblock(AVCodecContext *avctx, int *data, int level,
+ subband_t orientation, int width, int height, int x, int y) {
+ DiracContext *s = avctx->priv_data;
+ GetBitContext *gb = s->gb;
int blockcnt = s->codeblocksh[level] * s->codeblocksv[level];
int zero = 0;
- int bottom;
- int top;
- int left;
- int right;
+ int bottom = (subband_width(width, level) * x) / s->codeblocksh[level];
+ int top = (subband_width(width, level) * (x + 1)) / s->codeblocksh[level];
+ int left = (subband_height(height, level) * y) / s->codeblocksv[level];
+ int right = (subband_height(height, level) * (y + 1)) / s->codeblocksv[level];
+
+ int v, h;
if (blockcnt != 1) {
/* Determine if this codeblock is a zero block. */
@@ -773,14 +927,17 @@ static void codeblock (AVCodecContext *a
if (zero)
return; /* All coefficients remain 0. */
- /* XXX: Quantization. */
-
- // left = (width * x) /
+ for (v = bottom; v > top; v--)
+ for (h = right; h > left; h--)
+ coeff_unpack(avctx, data, level, orientation, v, h);
+ /* XXX: Quantization. */
}
-static int subband (AVCodecContext *avctx, GetBitContext *gb, int level, subband_t band) {
+static int subband(AVCodecContext *avctx, int *data, int level,
+ int width, int height, subband_t orientation) {
DiracContext *s = avctx->priv_data;
+ GetBitContext *gb = s->gb;
int length;
int quant;
int x, y;
@@ -796,28 +953,82 @@ static int subband (AVCodecContext *avct
quant = dirac_golomb(gb);
dprintf (avctx, "Length: %d, quant: %d\n", length, quant);
+
arith_init(gb, length);
for (y = 0; y < s->codeblocksv[level]; y++)
for (x = 0; x < s->codeblocksh[level]; x++)
- codeblock(avctx, gb, level, x, y);
+ codeblock(avctx, data, level, orientation, width, height, x, y);
arith_flush(gb);
}
+ /* XXX: For intra frames only. */
+ /* Intra DC prediction. */
+
return 0;
}
-static int decode_intra_frame(AVCodecContext *avctx, GetBitContext *gb,
+static int inline coeff_quant_factor(int idx) {
+ int base;
+ if (idx < 0)
+ idx = 0;
+ base = 1 << (idx / 4);
+ switch(idx & 3) {
+ case 0:
+ return base << 2;
+ case 1:
+ return (503829 * base + 52958) / 105917;
+ case 2:
+ return (665857 * idx + 58854) / 117708;
+ case 3:
+ return (440253 * base + 32722) / 65444;
+ }
+}
+
+static int inline coeff_quant_offset(int idx) {
+ if (idx == 0)
+ return 1;
+ /* XXX: Hardcode for intra frames. */
+ if (idx == 1)
+ return 2;
+ return (coeff_quant_factor(idx) + 1) >> 1;
+}
+
+static int inline coeff_dequant(int coeff, int idx) {
+ int64_t magnitude = abs(coeff) * coeff_quant_factor(idx);
+
+ if (! magnitude)
+ return 0;
+
+ magnitude += coeff_quant_offset(idx) + 2;
+ magnitude >>= 2;
+
+ /* Reintroduce the sign. */
+ if (coeff < 0)
+ magnitude = -magnitude;
+ return magnitude;
+}
+
+static int decode_intra_frame(AVCodecContext *avctx,
void *data, int *data_size) {
DiracContext *s = avctx->priv_data;
+ struct decoding_parameters decoding;
int picnum;
int retire;
+ int filter;
int i;
+ GetBitContext *gb = s->gb;
+
+ /* Setup decoding parameter defaults for this frame. */
+ memcpy(&decoding, &s->decoding, sizeof(decoding));
picnum = get_bits_long(gb, 32);
retire = dirac_golomb(gb);
+ for (i = 0; i < retire; i++)
+ dirac_golomb_sign(gb); /* XXX */
+
dprintf (avctx, "Picture #%d, retire: %d\n", picnum, retire);
align_get_bits(gb);
@@ -825,18 +1036,28 @@ static int decode_intra_frame(AVCodecCon
/* Wavelet transform data. */
/* XXX: Skip all interframe stuff for now. */
- /* Wavelet transform parameters. */
+ /* Override wavelet transform parameters. */
if (get_bits(gb, 1)) {
dprintf (avctx, "Non default filter\n");
+ filter = dirac_golomb(gb);
} else {
- dprintf (avctx, "Default filter, select (9, 3) for intra frame\n");
+ dprintf (avctx, "Default filter\n");
+ filter = decoding.wavelet_idx_intra;
}
- /* Wavelet depth. */
+ dprintf (avctx, "Wavelet filter: %d\n", filter);
+
+ if (filter == 0)
+ dprintf(avctx, "Wavelet filter: Deslauriers-Debuc (9,3)\n");
+ else
+ dprintf(avctx, "Unsupported filter\n");
+
+ /* Overrid wavelet depth. */
if (get_bits(gb, 1)) {
dprintf (avctx, "Non default depth\n");
+ decoding.wavelet_depth = dirac_golomb(gb);
}
- /* XXX: What's the default depth? reference implementation: 4 */
+ dprintf(avctx, "Depth: %d\n", decoding.wavelet_depth);
/* Spatial partitioning. */
if (get_bits(gb, 1)) {
@@ -844,13 +1065,21 @@ static int decode_intra_frame(AVCodecCon
dprintf (avctx, "Spatial partitioning\n");
+ /* Override the default partitioning. */
if (get_bits(gb, 1)) {
+ for (i = 0; i <= decoding.wavelet_depth; i++) {
+ s->codeblocksh[i] = dirac_golomb(gb);
+ s->codeblocksv[i] = dirac_golomb(gb);
+ }
+
dprintf (avctx, "Non-default partitioning\n");
+
} else {
/* Set defaults for the codeblocks. */
+ /* XXX: Hardcoded for intra frames. */
for (i = 0; i <= s->level; i++) {
- s->codeblocksv[i] = i <= 2 ? 1 : 4;
s->codeblocksh[i] = i <= 2 ? 1 : 3;
+ s->codeblocksv[i] = i <= 2 ? 1 : 4;
}
}
@@ -859,10 +1088,31 @@ static int decode_intra_frame(AVCodecCon
/* XXX: Here 0, so single quant. */
}
- /* Coefficient unpacking. */
+ /* Align for coefficient bitstream. */
+ align_get_bits(gb);
- /* Unpack LL, level 0. */
- subband (avctx, gb, 0, subband_ll);
+
+ /* Coefficient unpacking. XXX: This code will be rewritten. */
+ {
+ int width = s->sequence.luma_width;
+ int height = s->sequence.luma_height;
+ /* Rounded up to a multiple of 2^depth. */
+ s->padded_width = ((width + (1 << decoding.wavelet_depth) - 1) >> decoding.wavelet_depth) << decoding.wavelet_depth;
+ s->padded_height = ((height + (1 << decoding.wavelet_depth) - 1) >> decoding.wavelet_depth) << decoding.wavelet_depth;
+
+ {
+ /* XXX: Hardcode to a depth of 8. XXX: Change datatype.
+ Actually this is plain wrong and a frame has to be
+ allocated properly, but this is fine for testing. */
+ int frame[s->padded_width * s->padded_height];
+
+ dprintf(avctx, "width: %d, height: %d, padded width: %d, padded height: %d\n",
+ width, height, s->padded_width, s->padded_height);
+
+ /* Unpack LL, level 0. */
+ subband(avctx, frame, 0, width, height, subband_ll);
+ }
+ }
return 0;
}
@@ -876,12 +1126,13 @@ static int decode_frame(AVCodecContext *
dprintf (avctx, "Decoding frame: size=%d head=%c%c%c%c parse=%02x\n", buf_size, buf[0], buf[1], buf[2], buf[3], buf[4]);
init_get_bits(&gb, &buf[13], (buf_size - 13) * 8);
+ s->gb = &gb;
switch (parse_code) {
case pc_access_unit_header:
- return parse_access_unit_header (avctx, &gb);
+ return parse_access_unit_header (avctx);
case pc_intra_ref:
- return decode_intra_frame(avctx, &gb, data, data_size);
+ return decode_intra_frame(avctx, data, data_size);
}
*data_size = 0;
More information about the FFmpeg-soc
mailing list