Changeset 1008

Show
Ignore:
Timestamp:
01/01/09 22:18:05 (1 year ago)
Author:
gbooker
Message:

Added ability to force Perian's use with certain apps. This fixes iChat which seems to be incapable of conducting a complete codec search for some reason.
Added the ability to parse more of H.264's sps, in case it might be useful. Currently #ifed out as to not affect performance.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/CommonUtils.c

    r970 r1008  
    295295}; 
    296296 
     297static const CFStringRef defaultForcedAppList[] = { 
     298        CFSTR("iChat"), 
     299}; 
     300 
    297301static int findNameInList(CFStringRef loadingApp, const CFStringRef *names, int count) 
    298302{ 
     
    308312} 
    309313 
     314static CFDictionaryRef getMyProcessInformation() 
     315{ 
     316        ProcessSerialNumber myProcess; 
     317        GetCurrentProcess(&myProcess); 
     318        CFDictionaryRef processInformation; 
     319         
     320        processInformation = ProcessInformationCopyDictionary(&myProcess, kProcessDictionaryIncludeAllInformationMask); 
     321        return processInformation; 
     322} 
     323 
     324static CFStringRef getProcessName(CFDictionaryRef processInformation) 
     325{ 
     326        CFStringRef path = CFDictionaryGetValue(processInformation, kCFBundleExecutableKey); 
     327        CFRange entireRange = CFRangeMake(0, CFStringGetLength(path)), basename; 
     328         
     329        CFStringFindWithOptions(path, CFSTR("/"), entireRange, kCFCompareBackwards, &basename); 
     330         
     331        basename.location += 1; //advance past "/" 
     332        basename.length = entireRange.length - basename.location; 
     333         
     334        CFStringRef myProcessName = CFStringCreateWithSubstring(NULL, path, basename); 
     335        return myProcessName; 
     336} 
     337 
     338static int isApplicationNameInList(CFStringRef prefOverride, const CFStringRef *defaultList, unsigned int defaultListCount) 
     339{ 
     340        CFDictionaryRef processInformation = getMyProcessInformation(); 
     341         
     342        if (!processInformation) 
     343                return FALSE; 
     344         
     345        CFArrayRef list = CFPreferencesCopyAppValue(prefOverride, CFSTR("org.perian.Perian")); 
     346        if(list && CFGetTypeID(list) != CFArrayGetTypeID()) 
     347                list = NULL; 
     348         
     349        CFStringRef myProcessName = getProcessName(processInformation); 
     350        int ret; 
     351         
     352        if (list) { 
     353                int count = CFArrayGetCount(list); 
     354                CFStringRef names[count]; 
     355                 
     356                CFArrayGetValues(list, CFRangeMake(0, count), (void *)names); 
     357                ret = findNameInList(myProcessName, names, count); 
     358                CFRelease(list); 
     359        } else { 
     360                ret = findNameInList(myProcessName, defaultList, defaultListCount); 
     361        } 
     362        CFRelease(myProcessName); 
     363        CFRelease(processInformation); 
     364         
     365        return ret; 
     366} 
     367 
    310368int IsFrameDroppingEnabled() 
    311369{ 
    312370        static int enabled = -1; 
    313371         
    314         if (enabled == -1) { 
    315                 ProcessSerialNumber myProcess; 
    316                 GetCurrentProcess(&myProcess); 
    317                 CFDictionaryRef processInformation; 
    318                  
    319         processInformation = ProcessInformationCopyDictionary(&myProcess, kProcessDictionaryIncludeAllInformationMask); 
    320          
    321         if (!processInformation) enabled = FALSE; 
    322                 else { 
    323             CFArrayRef list = CFPreferencesCopyAppValue(CFSTR("FrameDroppingWhiteList"), CFSTR("org.perian.Perian")); 
    324                         if(list && CFGetTypeID(list) != CFArrayGetTypeID()) 
    325                                 list = NULL; 
    326             CFStringRef path = CFDictionaryGetValue(processInformation, kCFBundleExecutableKey); 
    327             CFRange entireRange = CFRangeMake(0, CFStringGetLength(path)), basename; 
    328              
    329             CFStringFindWithOptions(path, CFSTR("/"), entireRange, kCFCompareBackwards, &basename); 
    330              
    331             basename.location += 1; //advance past "/" 
    332             basename.length = entireRange.length - basename.location; 
    333              
    334             CFStringRef myProcessName = CFStringCreateWithSubstring(NULL, path, basename); 
    335              
    336             if (list) { 
    337                 int count = CFArrayGetCount(list); 
    338                 CFStringRef names[count]; 
    339                  
    340                 CFArrayGetValues(list, CFRangeMake(0, count), (void *)names); 
    341                 enabled = findNameInList(myProcessName, names, count); 
    342                 CFRelease(list); 
    343             } else { 
    344                 int count = sizeof(defaultFrameDroppingWhiteList)/sizeof(defaultFrameDroppingWhiteList[0]); 
    345                 enabled = findNameInList(myProcessName, defaultFrameDroppingWhiteList, count); 
    346             } 
    347             CFRelease(myProcessName); 
    348             CFRelease(processInformation); 
    349         } 
    350         } 
    351          
     372        if (enabled == -1) 
     373                enabled = isApplicationNameInList(CFSTR("FrameDroppingWhiteList"), 
     374                                                                                  defaultFrameDroppingWhiteList, 
     375                                                                                  sizeof(defaultFrameDroppingWhiteList)/sizeof(defaultFrameDroppingWhiteList[0])); 
    352376        return enabled; 
    353377} 
     378 
     379int forcePerianToDecode() 
     380{ 
     381        static int forced = -1; 
     382         
     383        if(forced == -1) 
     384                forced = isApplicationNameInList(CFSTR("ForcePerianAppList"), 
     385                                                                                 defaultForcedAppList, 
     386                                                                                 sizeof(defaultForcedAppList)/sizeof(defaultForcedAppList[0])); 
     387        return forced; 
     388} 
  • trunk/CommonUtils.h

    r887 r1008  
    4040 
    4141int IsFrameDroppingEnabled(); 
     42int forcePerianToDecode(); 
    4243 
    4344#ifdef __cplusplus 
  • trunk/FFusionCodec.c

    r1004 r1008  
    544544} 
    545545 
     546static inline int shouldDecode(FFusionGlobals glob, enum CodecID codecID) 
     547{ 
     548        FFusionDecodeAbilities decode = FFUSION_PREFER_DECODE; 
     549        if (glob->componentType == 'avc1') 
     550                decode = ffusionIsParsedVideoDecodable(glob->begin.parser); 
     551        if(decode > FFUSION_CANNOT_DECODE &&  
     552           (codecID == CODEC_ID_H264 || codecID == CODEC_ID_MPEG4) && CFPreferencesGetAppBooleanValue(CFSTR("PreferAppleCodecs"), PERIAN_PREF_DOMAIN, NULL)) 
     553                decode = FFUSION_PREFER_NOT_DECODE; 
     554        if(decode > FFUSION_CANNOT_DECODE) 
     555                if(forcePerianToDecode()) 
     556                        decode = FFUSION_PREFER_DECODE; 
     557        return decode > FFUSION_PREFER_NOT_DECODE; 
     558} 
     559 
    546560//----------------------------------------------------------------- 
    547561// ImageCodecPreflight 
     
    813827                        ffusionLogDebugInfo(glob->begin.parser, glob->fileLog); 
    814828                 
    815                 if ((glob->componentType == 'avc1' && !ffusionIsParsedVideoDecodable(glob->begin.parser)) || 
    816                         (codecID == CODEC_ID_H264 || codecID == CODEC_ID_MPEG4) && CFPreferencesGetAppBooleanValue(CFSTR("PreferAppleCodecs"), PERIAN_PREF_DOMAIN, NULL)) 
     829                if (!shouldDecode(glob, codecID)) 
    817830                        err = featureUnsupported; 
    818831                 
  • trunk/bitstream_info.c

    r1002 r1008  
    258258        int log2_max_frame_num; 
    259259        int frame_mbs_only_flag; 
     260        int num_reorder_frames; 
    260261        int pic_order_present_flag; 
    261262 
     
    337338} 
    338339 
     340static void skip_hrd_parameters(GetBitContext *gb) 
     341{ 
     342        int cpb_cnt_minus1 = get_ue_golomb(gb); 
     343        get_bits(gb, 4);        //bit_rate_scale 
     344        get_bits(gb, 4);        //cpb_size_scale 
     345        int i; 
     346        for(i=0; i<=cpb_cnt_minus1; i++) 
     347        { 
     348                get_ue_golomb(gb);      //bit_rate_value_minus1[i] 
     349                get_ue_golomb(gb);      //cpb_size_value_minus1[i] 
     350                get_bits1(gb);          //cbr_flag[i] 
     351        } 
     352        get_bits(gb, 5);        //initial_cpb_removal_delay_length_minus1 
     353        get_bits(gb, 5);        //cpb_removal_delay_length_minus1 
     354        get_bits(gb, 5);        //dpb_output_delay_length_minus1 
     355        get_bits(gb, 5);        //time_offset_length 
     356} 
     357 
    339358static void decode_sps(H264ParserContext *context, const uint8_t *buf, int buf_size) 
    340359{ 
     
    381400        get_ue_golomb(gb);      //pic_width_in_mbs_minus1 
    382401        get_ue_golomb(gb);      //pic_height_in_map_units_minus1 
    383         context->frame_mbs_only_flag = get_bits1(gb); 
     402        int mbs_only = get_bits1(gb); 
     403        context->frame_mbs_only_flag = mbs_only; 
     404#if 0           //This is a test to get num_reorder_frames 
     405        if(!mbs_only) 
     406                get_bits1(gb);  //mb_adaptive_frame_field_flag 
     407        get_bits1(gb);          //direct_8x8_inference_flag 
     408        if(get_bits1(gb))       //frame_cropping_flag 
     409        { 
     410                get_ue_golomb(gb);      //frame_crop_left_offset 
     411                get_ue_golomb(gb);      //frame_crop_right_offset 
     412                get_ue_golomb(gb);      //frame_crop_top_offset 
     413                get_ue_golomb(gb);      //frame_crop_bottom_offset 
     414        } 
     415        if(get_bits1(gb))       //vui_parameters_present_flag 
     416        { 
     417                if(get_bits1(gb))       //aspect_ratio_info_present_flag 
     418                { 
     419                        if(get_bits(gb, 8) == 255)      //aspect_ratio_idc 
     420                        { 
     421                                get_bits(gb, 16);       //sar_width 
     422                                get_bits(gb, 16);       //sar_height 
     423                        } 
     424                } 
     425                if(get_bits1(gb))       //overscan_info_present_flag 
     426                        get_bits1(gb);  //overscan_appropriate_flag 
     427                if(get_bits1(gb))       //video_signal_type_present_flag 
     428                { 
     429                        get_bits(gb, 3);        //video_format 
     430                        get_bits1(gb);          //video_full_range_flag 
     431                        if(get_bits1(gb))       //colour_description_present_flag 
     432                        { 
     433                                get_bits(gb, 8);        //colour_primaries 
     434                                get_bits(gb, 8);        //transfer_characteristics 
     435                                get_bits(gb, 8);        //matrix_coefficients 
     436                        } 
     437                } 
     438                if(get_bits1(gb))       //chroma_loc_info_present_flag 
     439                { 
     440                        get_ue_golomb(gb);      //chroma_sample_loc_type_top_field 
     441                        get_ue_golomb(gb);      //chroma_sample_loc_type_bottom_field 
     442                } 
     443                if(get_bits1(gb))       //timing_info_present_flag 
     444                { 
     445                        get_bits(gb, 32);       //num_units_in_tick 
     446                        get_bits(gb, 32);       //time_scale 
     447                        get_bits1(gb);  //fixed_frame_rate_flag 
     448                } 
     449                int nal_hrd_parameters_present_flag = get_bits1(gb); 
     450                if(nal_hrd_parameters_present_flag) 
     451                { 
     452                        skip_hrd_parameters(gb); 
     453                } 
     454                int vcl_hrd_parameters_present_flag = get_bits1(gb); 
     455                if(vcl_hrd_parameters_present_flag) 
     456                { 
     457                        skip_hrd_parameters(gb); 
     458                } 
     459                if(nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) 
     460                        get_bits1(gb);  //low_delay_hrd_flag 
     461                get_bits1(gb);  //pic_struct_present_flag 
     462                if(get_bits1(gb))       //bitstream_restriction_flag 
     463                { 
     464                        get_bits1(gb);  //motion_vectors_over_pic_boundaries_flag 
     465                        get_ue_golomb(gb);      //max_bytes_per_pic_denom 
     466                        get_ue_golomb(gb);      //max_bits_per_mb_denom 
     467                        get_ue_golomb(gb);      //log2_max_mv_length_horizontal 
     468                        get_ue_golomb(gb);      //log2_max_mv_length_vertical 
     469                        context->num_reorder_frames = get_ue_golomb(gb); 
     470                        get_ue_golomb(gb);      //max_dec_frame_buffering                        
     471                } 
     472        } 
     473#endif 
    384474} 
    385475 
     
    879969} 
    880970 
    881 int ffusionIsParsedVideoDecodable(FFusionParserContext *parser) 
    882 { 
    883         if (!parser) return 1
     971FFusionDecodeAbilities ffusionIsParsedVideoDecodable(FFusionParserContext *parser) 
     972{ 
     973        if (!parser) return FFUSION_PREFER_DECODE
    884974         
    885975        if (parser->parserStructure == &ffusionH264Parser) { 
    886976                H264ParserContext *h264parser = parser->internalContext; 
    887                 int no_decode = 0
     977                FFusionDecodeAbilities ret = FFUSION_PREFER_DECODE
    888978                 
    889979                //QT is bad at high profile 
    890980                //FIXME QT is also bad at B-pyramid (sps.vui.num_reorder_frames > 1) 
    891981                //but to parse that we should just use ffh264 directly 
    892                 no_decode |= h264parser->profile_idc < 100 && !CFPreferencesGetAppBooleanValue(CFSTR("DecodeAllProfiles"), CFSTR("org.perian.Perian"), NULL); 
     982                if(h264parser->profile_idc < 100 && !CFPreferencesGetAppBooleanValue(CFSTR("DecodeAllProfiles"), CFSTR("org.perian.Perian"), NULL)) 
     983                        ret = FFUSION_PREFER_NOT_DECODE; 
    893984                 
    894985                //PAFF/MBAFF 
    895986                //ffmpeg is ok at this now but we can't test it (not enough AVCHD samples) 
    896987                //and the quicktime api for it may or may not actually exist 
    897                 no_decode |= !h264parser->frame_mbs_only_flag; 
     988                if(!h264parser->frame_mbs_only_flag) 
     989                        ret = FFUSION_CANNOT_DECODE; 
    898990                 
    899991                //4:2:2 chroma 
    900                 no_decode |= h264parser->chroma_format_idc > 1; 
    901                  
    902                 return !no_decode; 
    903         } 
    904          
    905         return 1; 
     992                if(h264parser->chroma_format_idc > 1) 
     993                        ret = FFUSION_CANNOT_DECODE; 
     994                 
     995                return ret; 
     996        } 
     997         
     998        return FFUSION_PREFER_DECODE; 
    906999} 
    9071000#ifdef DEBUG_BUILD 
  • trunk/bitstream_info.h

    r989 r1008  
    3939} FFusionParser; 
    4040 
     41typedef enum { 
     42        FFUSION_CANNOT_DECODE, 
     43        FFUSION_PREFER_NOT_DECODE, 
     44        FFUSION_PREFER_DECODE, 
     45} FFusionDecodeAbilities; 
     46 
    4147void initFFusionParsers(); 
    4248FFusionParserContext *ffusionParserInit(int codec_id); 
     
    4450int ffusionParse(FFusionParserContext *parser, const uint8_t *buf, int buf_size, int *out_buf_size, int *type, int *skippable); 
    4551void ffusionLogDebugInfo(FFusionParserContext *parser, FILE *log); 
    46 int ffusionIsParsedVideoDecodable(FFusionParserContext *parser); 
     52FFusionDecodeAbilities ffusionIsParsedVideoDecodable(FFusionParserContext *parser); 
    4753 
    4854#ifdef __cplusplus