summaryrefslogtreecommitdiff
path: root/vstream
diff options
context:
space:
mode:
authorMarcin Koƛcielnicki <koriakin@0x04.net>2011-12-23 20:25:28 +0100
committerMarcin Koƛcielnicki <koriakin@0x04.net>2011-12-23 20:25:28 +0100
commit83d4e4dfd8161c4e496610f8b75e4fe4f9d95cac (patch)
treea8b7efcd958694721beeb343d9feae9c5bb5369e /vstream
parent830604c587448f246556e740fc9b83d2503ff615 (diff)
h264: mb_field_decoding_flag fixes
Diffstat (limited to 'vstream')
-rw-r--r--vstream/h264_slice.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/vstream/h264_slice.c b/vstream/h264_slice.c
index e7cfcf8f..b45a2aad 100644
--- a/vstream/h264_slice.c
+++ b/vstream/h264_slice.c
@@ -396,21 +396,28 @@ int h264_macroblock_layer(struct bitstream *str, struct h264_cabac_context *caba
return 0;
}
-int infer_skip(struct bitstream *str, struct h264_slice *slice, struct h264_macroblock *mb) {
+static int inferred_mb_field_decoding_flag(struct h264_slice *slice) {
+ if (slice->mbaff_frame_flag) {
+ const struct h264_macroblock *mbA = h264_mb_nb_p(slice, H264_MB_A, 0);
+ const struct h264_macroblock *mbB = h264_mb_nb_p(slice, H264_MB_B, 0);
+ if (mbA->mb_type != H264_MB_TYPE_UNAVAIL) {
+ return mbA->mb_field_decoding_flag;
+ } else if (mbB->mb_type != H264_MB_TYPE_UNAVAIL) {
+ return mbB->mb_field_decoding_flag;
+ } else {
+ return 0;
+ }
+ } else {
+ return slice->field_pic_flag;
+ }
+}
+
+static int infer_skip(struct bitstream *str, struct h264_slice *slice, struct h264_macroblock *mb) {
uint32_t skip_type = (slice->slice_type == H264_SLICE_TYPE_B ? H264_MB_TYPE_B_SKIP : H264_MB_TYPE_P_SKIP);
if (slice->mbaff_frame_flag) {
if (slice->curr_mb_addr & 1) {
if (h264_is_skip_mb_type(slice->mbs[slice->curr_mb_addr & ~1].mb_type)) {
- int val;
- const struct h264_macroblock *mbA = h264_mb_nb_p(slice, H264_MB_A, 0);
- const struct h264_macroblock *mbB = h264_mb_nb_p(slice, H264_MB_B, 0);
- if (mbA->mb_type != H264_MB_TYPE_UNAVAIL) {
- val = mbA->mb_field_decoding_flag;
- } else if (mbB->mb_type != H264_MB_TYPE_UNAVAIL) {
- val = mbB->mb_field_decoding_flag;
- } else {
- val = 0;
- }
+ int val = inferred_mb_field_decoding_flag(slice);
if (vs_infer(str, &mb[-1].mb_field_decoding_flag, val)) return 1;
}
if (vs_infer(str, &mb->mb_field_decoding_flag, mb[-1].mb_field_decoding_flag)) return 1;
@@ -450,7 +457,19 @@ int h264_slice_data(struct bitstream *str, struct h264_slice *slice) {
if (str->dir == VS_ENCODE) {
mb_skip_flag = slice->mbs[slice->curr_mb_addr].mb_type == skip_type;
}
+ /* mb_field_decoding_flag is decoded *after* mb_skip_flag in some circumstances, have to use an inferred value for CABAC prediction */
+ int save = slice->mbs[slice->curr_mb_addr].mb_field_decoding_flag;
+ int ival;
+ if (slice->mbaff_frame_flag
+ && slice->curr_mb_addr & 1
+ && slice->mbs[slice->curr_mb_addr - 1].mb_type != skip_type) {
+ ival = slice->mbs[slice->curr_mb_addr - 1].mb_field_decoding_flag;
+ } else {
+ ival = inferred_mb_field_decoding_flag(slice);
+ }
+ slice->mbs[slice->curr_mb_addr].mb_field_decoding_flag = ival;
if (h264_mb_skip_flag(str, cabac, &mb_skip_flag)) { h264_cabac_destroy(cabac); return 1; }
+ slice->mbs[slice->curr_mb_addr].mb_field_decoding_flag = save;
}
if (mb_skip_flag) {
if (infer_skip(str, slice, &slice->mbs[slice->curr_mb_addr])) { h264_cabac_destroy(cabac); return 1; }