Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksoid <aleksoid@users.sourceforge.net>2011-05-03 06:30:17 +0400
committerAleksoid <aleksoid@users.sourceforge.net>2011-05-03 06:30:17 +0400
commit789b5f8e6e8b6e0e57f57496c23b0fbd47f2c5d4 (patch)
tree0aa17656a507b8b18e88af6cd9f8118e934d8f41
parent2e988751140bd76842824e9ba82f7a65570825bd (diff)
Fix : MPEG Splitter can't recognize some H.264 video stream; (ticket #829);
Fix : Correctly read SPS/PPS split across two packets; Thanks to pwimmer for original patch; Fix : Internal H.264 decoder can't read some video; git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@3066 10f7b99b-c216-0410-bff0-8a66a9350fd8
-rw-r--r--src/filters/parser/BaseSplitter/BaseSplitterFileEx.cpp497
-rw-r--r--src/filters/parser/BaseSplitter/BaseSplitterFileEx.h30
-rw-r--r--src/filters/parser/MpegSplitter/MpegSplitterFile.cpp2
-rw-r--r--src/filters/transform/MPCVideoDec/ffmpeg/libavcodec/h264.c6
4 files changed, 241 insertions, 294 deletions
diff --git a/src/filters/parser/BaseSplitter/BaseSplitterFileEx.cpp b/src/filters/parser/BaseSplitter/BaseSplitterFileEx.cpp
index 434f08006..31db85b0e 100644
--- a/src/filters/parser/BaseSplitter/BaseSplitterFileEx.cpp
+++ b/src/filters/parser/BaseSplitter/BaseSplitterFileEx.cpp
@@ -27,8 +27,6 @@
#include <initguid.h>
#include <moreuuids.h>
-#define MAX_SPS 256 // Max size for a SPS packet
-
//
// CBaseSplitterFileEx
//
@@ -1253,7 +1251,6 @@ bool CBaseSplitterFileEx::Read(pvahdr& h, bool fSync)
return(true);
}
-
void CBaseSplitterFileEx::RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length)
{
int si=0;
@@ -1280,312 +1277,114 @@ void CBaseSplitterFileEx::RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length)
bool CBaseSplitterFileEx::Read(avchdr& h, int len, CMediaType* pmt)
{
- __int64 endpos = GetPos() + len; // - sequence header length
-
- DWORD dwStartCode;
-
- while(GetPos() < endpos+4 /*&& BitRead(32, true) == 0x00000001*/ && (!h.spslen || !h.ppslen)) {
- if (BitRead(32, true) != 0x00000001) {
- BitRead(8);
- continue;
- }
- __int64 pos = GetPos();
-
- BitRead(32);
- BYTE id = BitRead(8);
-
- if((id&0x9f) == 0x07 && (id&0x60) != 0) {
-#if 1
- BYTE SPSTemp[MAX_SPS];
- BYTE SPSBuff[MAX_SPS];
- CGolombBuffer gb (SPSBuff, MAX_SPS);
- __int64 num_units_in_tick;
- __int64 time_scale;
- long fixed_frame_rate_flag;
-
- h.spspos = pos;
-
- // Manage H264 escape codes (see "remove escapes (very rare 1:2^22)" in ffmpeg h264.c file)
- ByteRead((BYTE*)SPSTemp, MAX_SPS);
- RemoveMpegEscapeCode (SPSBuff, SPSTemp, MAX_SPS);
-
- h.profile = (BYTE)gb.BitRead(8);
- gb.BitRead(8);
- h.level = (BYTE)gb.BitRead(8);
-
- gb.UExpGolombRead(); // seq_parameter_set_id
-
- if(h.profile >= 100) { // high profile
- if(gb.UExpGolombRead() == 3) { // chroma_format_idc
- gb.BitRead(1); // residue_transform_flag
- }
-
- gb.UExpGolombRead(); // bit_depth_luma_minus8
- gb.UExpGolombRead(); // bit_depth_chroma_minus8
+ __int64 endpos = GetPos() + len;
+ __int64 nalstartpos = GetPos();
+ __int64 nalendpos;
+ bool repeat = false;
- gb.BitRead(1); // qpprime_y_zero_transform_bypass_flag
-
- if(gb.BitRead(1)) // seq_scaling_matrix_present_flag
- for(int i = 0; i < 8; i++)
- if(gb.BitRead(1)) // seq_scaling_list_present_flag
- for(int j = 0, size = i < 6 ? 16 : 64, next = 8; j < size && next != 0; ++j) {
- next = (next + gb.SExpGolombRead() + 256) & 255;
- }
- }
-
- gb.UExpGolombRead(); // log2_max_frame_num_minus4
-
- UINT64 pic_order_cnt_type = gb.UExpGolombRead();
-
- if(pic_order_cnt_type == 0) {
- gb.UExpGolombRead(); // log2_max_pic_order_cnt_lsb_minus4
- } else if(pic_order_cnt_type == 1) {
- gb.BitRead(1); // delta_pic_order_always_zero_flag
- gb.SExpGolombRead(); // offset_for_non_ref_pic
- gb.SExpGolombRead(); // offset_for_top_to_bottom_field
- UINT64 num_ref_frames_in_pic_order_cnt_cycle = gb.UExpGolombRead();
- for(int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
- gb.SExpGolombRead(); // offset_for_ref_frame[i]
- }
- }
-
- gb.UExpGolombRead(); // num_ref_frames
- gb.BitRead(1); // gaps_in_frame_num_value_allowed_flag
-
- UINT64 pic_width_in_mbs_minus1 = gb.UExpGolombRead();
- UINT64 pic_height_in_map_units_minus1 = gb.UExpGolombRead();
- BYTE frame_mbs_only_flag = (BYTE)gb.BitRead(1);
-
- h.width = (pic_width_in_mbs_minus1 + 1) * 16;
- h.height = (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;
-
- if (h.height == 1088) {
- h.height = 1080; // Prevent blur lines
- }
-
- if (!frame_mbs_only_flag) {
- gb.BitRead(1); // mb_adaptive_frame_field_flag
- }
- gb.BitRead(1); // direct_8x8_inference_flag
- if (gb.BitRead(1)) { // frame_cropping_flag
- gb.UExpGolombRead(); // frame_cropping_rect_left_offset
- gb.UExpGolombRead(); // frame_cropping_rect_right_offset
- gb.UExpGolombRead(); // frame_cropping_rect_top_offset
- gb.UExpGolombRead(); // frame_cropping_rect_bottom_offset
- }
-
- if (gb.BitRead(1)) { // vui_parameters_present_flag
- if (gb.BitRead(1)) { // aspect_ratio_info_present_flag
- if (255==(BYTE)gb.BitRead(8)) { // aspect_ratio_idc)
- gb.BitRead(16); // sar_width
- gb.BitRead(16); // sar_height
- }
- }
+ // At least a SPS (normal or subset) and a PPS is required
+ while(GetPos() < endpos+4 && (!h.spspps[index_sps].complete || !h.spspps[index_pps].complete || repeat))
+ {
+ BYTE id = h.lastid;
+ repeat = false;
- if (gb.BitRead(1)) { // overscan_info_present_flag
- gb.BitRead(1); // overscan_appropriate_flag
- }
+ // Get array index from NAL unit type
+ spsppsindex index = index_unknown;
- if (gb.BitRead(1)) { // video_signal_type_present_flag
- gb.BitRead(3); // video_format
- gb.BitRead(1); // video_full_range_flag
- if(gb.BitRead(1)) { // colour_description_present_flag
- gb.BitRead(8); // colour_primaries
- gb.BitRead(8); // transfer_characteristics
- gb.BitRead(8); // matrix_coefficients
- }
- }
- if(gb.BitRead(1)) { // chroma_location_info_present_flag
- gb.UExpGolombRead(); // chroma_sample_loc_type_top_field
- gb.UExpGolombRead(); // chroma_sample_loc_type_bottom_field
- }
- if (gb.BitRead(1)) { // timing_info_present_flag
- num_units_in_tick = gb.BitRead(32);
- time_scale = gb.BitRead(32);
- fixed_frame_rate_flag = gb.BitRead(1);
-
- // Trick for weird parameters (10x to Madshi)!
- if ((num_units_in_tick < 1000) || (num_units_in_tick > 1001)) {
- if ((time_scale % num_units_in_tick != 0) && ((time_scale*1001) % num_units_in_tick == 0)) {
- time_scale = (time_scale * 1001) / num_units_in_tick;
- num_units_in_tick = 1001;
- } else {
- time_scale = (time_scale * 1000) / num_units_in_tick;
- num_units_in_tick = 1000;
- }
- }
- time_scale = time_scale / 2; // VUI consider fields even for progressive stream : divide by 2!
-
- if (time_scale) {
- h.AvgTimePerFrame = (10000000I64*num_units_in_tick)/time_scale;
- }
- }
+ if((id&0x60) != 0) {
+ if((id&0x9f) == 0x07) {
+ index = index_sps;
+ } else if((id&0x9f) == 0x08) {
+ index = h.spspps[index_pps].complete ? index_pps2 : index_pps;
}
+ }
- Seek(h.spspos+gb.GetPos());
-#else
- __int64 num_units_in_tick;
- __int64 time_scale;
- long fixed_frame_rate_flag;
-
- h.spspos = pos;
-
- h.profile = (BYTE)BitRead(8);
+ // Search for next start code
+ DWORD dwStartCode = BitRead(32, true);
+ while(GetPos() < endpos+4 && (dwStartCode != 0x00000001) && (dwStartCode & 0xFFFFFF00) != 0x00000100) {
BitRead(8);
- h.level = (BYTE)BitRead(8);
-
- UExpGolombRead(); // seq_parameter_set_id
-
- if(h.profile >= 100) { // high profile
- if(UExpGolombRead() == 3) { // chroma_format_idc
- BitRead(1); // residue_transform_flag
- }
-
- UExpGolombRead(); // bit_depth_luma_minus8
- UExpGolombRead(); // bit_depth_chroma_minus8
-
- BitRead(1); // qpprime_y_zero_transform_bypass_flag
-
- if(BitRead(1)) // seq_scaling_matrix_present_flag
- for(int i = 0; i < 8; i++)
- if(BitRead(1)) // seq_scaling_list_present_flag
- for(int j = 0, size = i < 6 ? 16 : 64, next = 8; j < size && next != 0; ++j) {
- next = (next + SExpGolombRead() + 256) & 255;
- }
- }
-
- UExpGolombRead(); // log2_max_frame_num_minus4
-
- UINT64 pic_order_cnt_type = UExpGolombRead();
-
- if(pic_order_cnt_type == 0) {
- UExpGolombRead(); // log2_max_pic_order_cnt_lsb_minus4
- } else if(pic_order_cnt_type == 1) {
- BitRead(1); // delta_pic_order_always_zero_flag
- SExpGolombRead(); // offset_for_non_ref_pic
- SExpGolombRead(); // offset_for_top_to_bottom_field
- UINT64 num_ref_frames_in_pic_order_cnt_cycle = UExpGolombRead();
- for(int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
- SExpGolombRead(); // offset_for_ref_frame[i]
- }
- }
-
- UExpGolombRead(); // num_ref_frames
- BitRead(1); // gaps_in_frame_num_value_allowed_flag
-
- UINT64 pic_width_in_mbs_minus1 = UExpGolombRead();
- UINT64 pic_height_in_map_units_minus1 = UExpGolombRead();
- BYTE frame_mbs_only_flag = (BYTE)BitRead(1);
-
- h.width = (pic_width_in_mbs_minus1 + 1) * 16;
- h.height = (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;
-
- if (h.height == 1088) {
- h.height = 1080; // Prevent blur lines
- }
+ dwStartCode = BitRead(32, true);
+ }
- if (!frame_mbs_only_flag) {
- BitRead(1); // mb_adaptive_frame_field_flag
- }
- BitRead(1); // direct_8x8_inference_flag
- if (BitRead(1)) { // frame_cropping_flag
- UExpGolombRead(); // frame_cropping_rect_left_offset
- UExpGolombRead(); // frame_cropping_rect_right_offset
- UExpGolombRead(); // frame_cropping_rect_top_offset
- UExpGolombRead(); // frame_cropping_rect_bottom_offset
- }
+ nalendpos = GetPos();
- if (BitRead(1)) { // vui_parameters_present_flag
- if (BitRead(1)) { // aspect_ratio_info_present_flag
- if (255==(BYTE)BitRead(8)) { // aspect_ratio_idc)
- BitRead(16); // sar_width
- BitRead(16); // sar_height
- }
- }
+ // Skip start code
+ __int64 pos;
+ if(GetPos() < endpos+4) {
+ if (dwStartCode == 0x00000001)
+ BitRead(32);
+ else
+ BitRead(24);
- if (BitRead(1)) { // overscan_info_present_flag
- BitRead(1); // overscan_appropriate_flag
- }
+ pos = GetPos();
+ h.lastid = BitRead(8);
+ } else {
+ pos = GetPos()-4;
+ }
- if (BitRead(1)) { // video_signal_type_present_flag
- BitRead(3); // video_format
- BitRead(1); // video_full_range_flag
- if(BitRead(1)) { // colour_description_present_flag
- BitRead(8); // colour_primaries
- BitRead(8); // transfer_characteristics
- BitRead(8); // matrix_coefficients
+ // The SPS or PPS might be fragmented, copy data into buffer until NAL is complete
+ if(index >= 0) {
+ if(h.spspps[index].complete) {
+ // Don't handle SPS/PPS twice
+ continue;
+ } else if(pos > nalstartpos) {
+ // Copy into buffer
+ Seek(nalstartpos);
+ int bufsize = countof(h.spspps[index].buffer);
+ int len = min(bufsize - h.spspps[index].size, pos - nalstartpos);
+ ByteRead(h.spspps[index].buffer+h.spspps[index].size, len);
+ Seek(pos);
+ h.spspps[index].size += len;
+
+ ASSERT(h.spspps[index].size < bufsize);
+
+ if(h.spspps[index].size >= bufsize || dwStartCode == 0x00000001 || (dwStartCode & 0xFFFFFF00) == 0x00000100) {
+ if (Read(h, index)) {
+ h.spspps[index].complete = true;
+ h.spspps[index].size -= 4;
+ } else {
+ h.spspps[index].size = 0;
}
}
- if(BitRead(1)) { // chroma_location_info_present_flag
- UExpGolombRead(); // chroma_sample_loc_type_top_field
- UExpGolombRead(); // chroma_sample_loc_type_bottom_field
- }
- if (BitRead(1)) { // timing_info_present_flag
- num_units_in_tick = BitRead(32);
- time_scale = BitRead(32);
- fixed_frame_rate_flag = BitRead(1);
-
- // Trick for weird parameters (10x to Madshi)!
- if ((num_units_in_tick < 1000) || (num_units_in_tick > 1001)) {
- if ((time_scale % num_units_in_tick != 0) && ((time_scale*1001) % num_units_in_tick == 0)) {
- time_scale = (time_scale * 1001) / num_units_in_tick;
- num_units_in_tick = 1001;
- } else {
- time_scale = (time_scale * 1000) / num_units_in_tick;
- num_units_in_tick = 1000;
- }
- }
- time_scale = time_scale / 2; // VUI consider fields even for progressive stream : divide by 2!
- if (time_scale) {
- h.AvgTimePerFrame = (10000000I64*num_units_in_tick)/time_scale;
- }
- }
+ repeat = true;
}
-#endif
- } else if((id&0x9f) == 0x08 && (id&0x60) != 0) {
- h.ppspos = pos;
- }
-
- BitByteAlign();
-
- dwStartCode = BitRead(32, true);
- while(GetPos() < endpos+4 && (dwStartCode != 0x00000001) && (dwStartCode & 0xFFFFFF00) != 0x00000100) {
- BitRead(8);
- dwStartCode = BitRead(32, true);
- }
-
- if(h.spspos != 0 && h.spslen == 0) {
- h.spslen = GetPos() - h.spspos;
- }
- if(h.ppspos != 0 && h.ppslen == 0) {
- h.ppslen = GetPos() - h.ppspos;
}
+ nalstartpos = pos;
}
- if(!h.spspos || !h.spslen || !h.ppspos || !h.ppslen || h.height<300 || h.width<300) {
+ // Exit and wait for next packet if there is no SPS and PPS yet
+ if(!h.spspps[index_sps].complete || !h.spspps[index_pps].complete || repeat) {
return(false);
}
if(!((h.level == 10) || (h.level == 11) || (h.level == 12) ||
- (h.level == 13) || (h.level == 20) || (h.level == 21) ||
+ (h.level == 13) || (h.level == 20) || (h.level == 21) ||
(h.level == 22) || (h.level == 30) || (h.level == 31) ||
(h.level == 32) || (h.level == 40) || (h.level == 41) ||
(h.level == 42) || (h.level == 50) || (h.level == 51))) {
return(false);
}
+ if(h.height<300 || h.width<300) {
+ return(false);
+ }
+
if(!pmt) {
return(true);
}
{
- int extra = 2+h.spslen-4 + 2+h.ppslen-4;
+ // Calculate size of extra data
+ int extra = 0;
+ for(int i = 0; i < 3; i++) {
+ if(h.spspps[i].complete)
+ extra += 2+(h.spspps[i].size);
+ }
pmt->majortype = MEDIATYPE_Video;
- pmt->subtype = FOURCCMap('1CVA');
- //pmt->subtype = MEDIASUBTYPE_H264; // TODO : put MEDIASUBTYPE_H264 to support Windows 7 decoder !
+ pmt->subtype = FOURCCMap('1CVA'); // AVC stream
pmt->formattype = FORMAT_MPEG2_VIDEO;
int len = FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + extra;
MPEG2VIDEOINFO* vi = (MPEG2VIDEOINFO*)DNew BYTE[len];
@@ -1602,17 +1401,18 @@ bool CBaseSplitterFileEx::Read(avchdr& h, int len, CMediaType* pmt)
vi->dwFlags = 4; // ?
vi->dwLevel = h.level;
vi->cbSequenceHeader = extra;
+
+ // Copy extra data
BYTE* p = (BYTE*)&vi->dwSequenceHeader[0];
- *p++ = (h.spslen-4) >> 8;
- *p++ = (h.spslen-4) & 0xff;
- Seek(h.spspos+4);
- ByteRead(p, h.spslen-4);
- p += h.spslen-4;
- *p++ = (h.ppslen-4) >> 8;
- *p++ = (h.ppslen-4) & 0xff;
- Seek(h.ppspos+4);
- ByteRead(p, h.ppslen-4);
- p += h.ppslen-4;
+ for(int i = 0; i < 3; i++) {
+ if(h.spspps[i].complete) {
+ *p++ = (h.spspps[i].size) >> 8;
+ *p++ = (h.spspps[i].size) & 0xff;
+ memcpy(p, h.spspps[i].buffer, h.spspps[i].size);
+ p += h.spspps[i].size;
+ }
+ }
+
pmt->SetFormat((BYTE*)vi, len);
delete [] vi;
}
@@ -1620,6 +1420,135 @@ bool CBaseSplitterFileEx::Read(avchdr& h, int len, CMediaType* pmt)
return(true);
}
+bool CBaseSplitterFileEx::Read(avchdr& h, spsppsindex index)
+{
+ // Only care about SPS and subset SPS
+ if(index != index_sps)
+ return true;
+
+ // Manage escape codes
+ BYTE buffer[MAX_SPSPPS];
+ RemoveMpegEscapeCode(buffer, h.spspps[index].buffer, MAX_SPSPPS);
+ CGolombBuffer gb(buffer, MAX_SPSPPS);
+
+ gb.BitRead(8); // nal_unit_type
+ h.profile = (BYTE)gb.BitRead(8);
+ gb.BitRead(8);
+ h.level = (BYTE)gb.BitRead(8);
+
+ gb.UExpGolombRead(); // seq_parameter_set_id
+
+ if(h.profile >= 100) { // high profile
+ if(gb.UExpGolombRead() == 3) { // chroma_format_idc
+ gb.BitRead(1); // residue_transform_flag
+ }
+
+ gb.UExpGolombRead(); // bit_depth_luma_minus8
+ gb.UExpGolombRead(); // bit_depth_chroma_minus8
+
+ gb.BitRead(1); // qpprime_y_zero_transform_bypass_flag
+
+ if(gb.BitRead(1)) { // seq_scaling_matrix_present_flag
+ for(int i = 0; i < 8; i++) {
+ if(gb.BitRead(1)) { // seq_scaling_list_present_flag
+ for(int j = 0, size = i < 6 ? 16 : 64, next = 8; j < size && next != 0; ++j) {
+ next = (next + gb.SExpGolombRead() + 256) & 255;
+ }
+ }
+ }
+ }
+ }
+
+ gb.UExpGolombRead(); // log2_max_frame_num_minus4
+
+ UINT64 pic_order_cnt_type = gb.UExpGolombRead();
+
+ if(pic_order_cnt_type == 0) {
+ gb.UExpGolombRead(); // log2_max_pic_order_cnt_lsb_minus4
+ } else if(pic_order_cnt_type == 1) {
+ gb.BitRead(1); // delta_pic_order_always_zero_flag
+ gb.SExpGolombRead(); // offset_for_non_ref_pic
+ gb.SExpGolombRead(); // offset_for_top_to_bottom_field
+ UINT64 num_ref_frames_in_pic_order_cnt_cycle = gb.UExpGolombRead();
+ for(int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
+ gb.SExpGolombRead(); // offset_for_ref_frame[i]
+ }
+ }
+
+ gb.UExpGolombRead(); // num_ref_frames
+ gb.BitRead(1); // gaps_in_frame_num_value_allowed_flag
+
+ UINT64 pic_width_in_mbs_minus1 = gb.UExpGolombRead();
+ UINT64 pic_height_in_map_units_minus1 = gb.UExpGolombRead();
+ BYTE frame_mbs_only_flag = (BYTE)gb.BitRead(1);
+
+ h.width = (pic_width_in_mbs_minus1 + 1) * 16;
+ h.height = (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;
+
+ if(h.height == 1088) {
+ h.height = 1080; // Prevent blur lines
+ }
+
+ if(!frame_mbs_only_flag) {
+ gb.BitRead(1); // mb_adaptive_frame_field_flag
+ }
+ gb.BitRead(1); // direct_8x8_inference_flag
+ if(gb.BitRead(1)) { // frame_cropping_flag
+ gb.UExpGolombRead(); // frame_cropping_rect_left_offset
+ gb.UExpGolombRead(); // frame_cropping_rect_right_offset
+ gb.UExpGolombRead(); // frame_cropping_rect_top_offset
+ gb.UExpGolombRead(); // frame_cropping_rect_bottom_offset
+ }
+
+ if(gb.BitRead(1)) { // vui_parameters_present_flag
+ if(gb.BitRead(1)) { // aspect_ratio_info_present_flag
+ if(255==(BYTE)gb.BitRead(8)) { // aspect_ratio_idc
+ gb.BitRead(16); // sar_width
+ gb.BitRead(16); // sar_height
+ }
+ }
+
+ if(gb.BitRead(1)) { // overscan_info_present_flag
+ gb.BitRead(1); // overscan_appropriate_flag
+ }
+
+ if(gb.BitRead(1)) { // video_signal_type_present_flag
+ gb.BitRead(3); // video_format
+ gb.BitRead(1); // video_full_range_flag
+ if(gb.BitRead(1)) { // colour_description_present_flag
+ gb.BitRead(8); // colour_primaries
+ gb.BitRead(8); // transfer_characteristics
+ gb.BitRead(8); // matrix_coefficients
+ }
+ }
+ if(gb.BitRead(1)) { // chroma_location_info_present_flag
+ gb.UExpGolombRead(); // chroma_sample_loc_type_top_field
+ gb.UExpGolombRead(); // chroma_sample_loc_type_bottom_field
+ }
+ if(gb.BitRead(1)) { // timing_info_present_flag
+ __int64 num_units_in_tick = gb.BitRead(32);
+ __int64 time_scale = gb.BitRead(32);
+ long fixed_frame_rate_flag = gb.BitRead(1);
+
+ // Trick for weird parameters
+ if ((num_units_in_tick < 1000) || (num_units_in_tick > 1001)) {
+ if ((time_scale % num_units_in_tick != 0) && ((time_scale*1001) % num_units_in_tick == 0)) {
+ time_scale = (time_scale * 1001) / num_units_in_tick;
+ num_units_in_tick = 1001;
+ } else {
+ time_scale = (time_scale * 1000) / num_units_in_tick;
+ num_units_in_tick = 1000;
+ }
+ }
+ time_scale = time_scale / 2; // VUI consider fields even for progressive stream : divide by 2!
+
+ if (time_scale) {
+ h.AvgTimePerFrame = (10000000I64*num_units_in_tick)/time_scale;
+ }
+ }
+ }
+ return true;
+}
bool CBaseSplitterFileEx::Read(vc1hdr& h, int len, CMediaType* pmt, int guid_flag)
{
diff --git a/src/filters/parser/BaseSplitter/BaseSplitterFileEx.h b/src/filters/parser/BaseSplitter/BaseSplitterFileEx.h
index 4235ef024..23571c4b2 100644
--- a/src/filters/parser/BaseSplitter/BaseSplitterFileEx.h
+++ b/src/filters/parser/BaseSplitter/BaseSplitterFileEx.h
@@ -23,6 +23,8 @@
#include "BaseSplitterFile.h"
+#define MAX_SPSPPS 256 // Max size for a SPS/PPS packet
+
class CBaseSplitterFileEx : public CBaseSplitterFile
{
int m_tslen; // transport stream packet length (188 or 192 bytes, auto-detected)
@@ -319,18 +321,31 @@ public:
REFERENCE_TIME pts;
};
+ enum spsppsindex {
+ index_unknown = -1,
+ index_sps = 1,
+ index_pps = 2,
+ index_pps2 = 3,
+ };
+
+ struct spsppsdata {
+ BYTE buffer[MAX_SPSPPS];
+ unsigned int size;
+ bool complete;
+ };
+
struct avchdr {
BYTE profile, level;
unsigned int width, height;
- __int64 spspos, spslen;
- __int64 ppspos, ppslen;
__int64 AvgTimePerFrame;
- avchdr() {
- spspos = 0;
- spslen = 0;
- ppspos = 0;
- ppslen = 0;
+ spsppsdata spspps[3];
+ BYTE lastid;
+
+ avchdr()
+ {
+ memset(spspps, 0, sizeof(spspps));
+ lastid = 0;
AvgTimePerFrame = 0;
}
};
@@ -379,6 +394,7 @@ public:
bool Read(avchdr& h, int len, CMediaType* pmt = NULL);
bool Read(vc1hdr& h, int len, CMediaType* pmt = NULL, int guid_flag = 1);
bool Read(dvbsub& h, int len, CMediaType* pmt = NULL);
+ bool Read(avchdr& h, spsppsindex index);
void RemoveMpegEscapeCode(BYTE* dst, BYTE* src, int length);
};
diff --git a/src/filters/parser/MpegSplitter/MpegSplitterFile.cpp b/src/filters/parser/MpegSplitter/MpegSplitterFile.cpp
index fef98da22..0a2ebe0ca 100644
--- a/src/filters/parser/MpegSplitter/MpegSplitterFile.cpp
+++ b/src/filters/parser/MpegSplitter/MpegSplitterFile.cpp
@@ -131,7 +131,7 @@ HRESULT CMpegSplitterFile::Init(IAsyncReader* pAsyncReader)
__int64 fp = fps.RemoveHead();
fp = min(GetLength() - MEGABYTE/8, fp);
fp = max(pfp, fp);
- __int64 nfp = fp + (pfp == 0 ? 5*MEGABYTE : MEGABYTE/8);
+ __int64 nfp = fp + (pfp == 0 ? 10*MEGABYTE : MEGABYTE/8);
if(FAILED(hr = SearchStreams(fp, nfp, pAsyncReader))) {
return hr;
}
diff --git a/src/filters/transform/MPCVideoDec/ffmpeg/libavcodec/h264.c b/src/filters/transform/MPCVideoDec/ffmpeg/libavcodec/h264.c
index 291db91c1..54b7d5a80 100644
--- a/src/filters/transform/MPCVideoDec/ffmpeg/libavcodec/h264.c
+++ b/src/filters/transform/MPCVideoDec/ffmpeg/libavcodec/h264.c
@@ -836,9 +836,11 @@ int ff_h264_decode_extradata(H264Context *h)
// Decode pps from avcC
for (i = 0; p<pend-2; i++) {
nalsize = AV_RB16(p) + 2;
- if(decode_nal_units(h, p, nalsize) != nalsize) {
+ if(decode_nal_units(h, p, nalsize) != nalsize) {
av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i);
- return -1;
+ // ==> Start patch MPC
+ //return -1;
+ // <== End patch MPC
}
p += nalsize;
}