Skip to content

Commit

Permalink
Fix field order detection of frames coded as fields
Browse files Browse the repository at this point in the history
The field order of frames coded as two field pictures was always
detected as bottom field first. The top_field_first bit is actually not
applicable to field pictures. Instead, use the order in which the field
pictures appear in the stream.

Bug present since v1.
  • Loading branch information
cantabile committed Jun 15, 2020
1 parent 1fd2027 commit c5afc74
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AC_INIT([D2VWitch], [4], [https://github.com/dubhater/D2VWitch/issues], [D2VWitch], [https://github.com/dubhater/D2VWitch])
AC_INIT([D2VWitch], [5], [https://github.com/dubhater/D2VWitch/issues], [D2VWitch], [https://github.com/dubhater/D2VWitch])

: ${CFLAGS=""}
: ${CXXFLAGS=""}
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project('d2vwitch', 'cpp',
version: '4',
version: '5',
default_options: ['cpp_std=c++11', 'buildtype=release'],
meson_version: '>=0.46')

Expand Down
24 changes: 24 additions & 0 deletions src/MPEGParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ static const uint8_t *findStartCode(const uint8_t *data, const uint8_t *data_end
void d2vWitchParseMPEG12Data(AVCodecParserContext *parser, AVCodecContext *avctx, const uint8_t *data, int data_size) {
clear(parser, avctx);

// It seems that when a frame is encoded as two field pictures
// av_read_frame returns both pictures in the same packet,
// so one packet is counted as one frame in the calling function.
// So we pretend to the calling function that we received a frame
// picture.
parser->picture_structure = AV_PICTURE_STRUCTURE_FRAME;

// Maybe not the best idea, but it's really the only thing that needs to be remembered between calls
Expand Down Expand Up @@ -141,10 +146,26 @@ void d2vWitchParseMPEG12Data(AVCodecParserContext *parser, AVCodecContext *avctx
}
} else if (extension_type == PICTURE_CODING_EXTENSION) {
if (bytes_left >= 5) {
int picture_structure = data[2] & 3;
int top_field_first = data[3] & (1 << 7);
int repeat_first_field = data[3] & (1 << 1);
int progressive_frame = data[4] & (1 << 7);

if (picture_structure != AV_PICTURE_STRUCTURE_FRAME) {
// When the picture is a field picture,
// top_field_first has to be always 0,
// and the field order is determined by
// which field appears first in the stream.

// This code here only ever looks at the
// first picture in the pair.

// When picture_structure is not "Frame",
// progressive_frame has to be 0, thankfully.

top_field_first = picture_structure == AV_PICTURE_STRUCTURE_TOP_FIELD;
}

parser->repeat_pict = 1;

if (repeat_first_field) {
Expand Down Expand Up @@ -179,6 +200,9 @@ void d2vWitchParseMPEG12Data(AVCodecParserContext *parser, AVCodecContext *avctx
}
} else if (start_code == 0xffffffff ||
(start_code >= SLICE_START_CODE_MIN && start_code <= SLICE_START_CODE_MAX)) {
// Even if we received two field pictures in this packet,
// we only need to look at the first picture. We can skip
// the second one.
break;
}
}
Expand Down

0 comments on commit c5afc74

Please sign in to comment.