| 817 | | } |
|---|
| | 818 | } |
|---|
| | 819 | |
|---|
| | 820 | typedef struct { |
|---|
| | 821 | Movie theMovie; |
|---|
| | 822 | OSType dataRefType; |
|---|
| | 823 | Handle dataRef; |
|---|
| | 824 | int imageWidth; |
|---|
| | 825 | int imageHeight; |
|---|
| | 826 | Rect movieBox; |
|---|
| | 827 | NSData *subFileData; |
|---|
| | 828 | } VobSubInfo; |
|---|
| | 829 | |
|---|
| | 830 | static OSErr loadTrackIntoMovie(VobSubTrack *track, VobSubInfo info, uint8_t onlyForced, Track *theTrack, uint8_t *hasForcedSubtitles) |
|---|
| | 831 | { |
|---|
| | 832 | ImageDescriptionHandle imgDesc; |
|---|
| | 833 | Media trackMedia = createVobSubMedia(info.theMovie, info.movieBox, &imgDesc, info.dataRef, info.dataRefType, track); |
|---|
| | 834 | if(info.imageWidth != 0) |
|---|
| | 835 | { |
|---|
| | 836 | (*imgDesc)->width = info.imageWidth; |
|---|
| | 837 | (*imgDesc)->height = info.imageHeight; |
|---|
| | 838 | } |
|---|
| | 839 | |
|---|
| | 840 | int sampleCount = [track->samples count]; |
|---|
| | 841 | int totalSamples = 0; |
|---|
| | 842 | SampleReference64Ptr samples = (SampleReference64Ptr)calloc(sampleCount*2, sizeof(SampleReference64Record)); |
|---|
| | 843 | SampleReference64Ptr sample = samples; |
|---|
| | 844 | int i; |
|---|
| | 845 | uint32_t lastTime = 0; |
|---|
| | 846 | VobSubSample *firstSample = nil; |
|---|
| | 847 | for(i=0; i<sampleCount; i++) |
|---|
| | 848 | { |
|---|
| | 849 | VobSubSample *currentSample = [track->samples objectAtIndex:i]; |
|---|
| | 850 | int offset = currentSample->fileOffset; |
|---|
| | 851 | int nextOffset; |
|---|
| | 852 | if(i == sampleCount - 1) |
|---|
| | 853 | nextOffset = [info.subFileData length]; |
|---|
| | 854 | else |
|---|
| | 855 | nextOffset = ((VobSubSample *)[track->samples objectAtIndex:i+1])->fileOffset; |
|---|
| | 856 | int size = nextOffset - offset; |
|---|
| | 857 | if(size < 0) |
|---|
| | 858 | //Skip samples for which we cannot determine size |
|---|
| | 859 | continue; |
|---|
| | 860 | |
|---|
| | 861 | NSData *subData = [info.subFileData subdataWithRange:NSMakeRange(offset, size)]; |
|---|
| | 862 | uint8_t *extracted = (uint8_t *)malloc(size); |
|---|
| | 863 | int extractedSize = ExtractVobSubPacket(extracted, (const UInt8 *)[subData bytes], size, &size); |
|---|
| | 864 | |
|---|
| | 865 | uint16_t startTimestamp, endTimestamp; |
|---|
| | 866 | uint8_t forced; |
|---|
| | 867 | ReadPacketTimes(extracted, extractedSize, &startTimestamp, &endTimestamp, &forced); |
|---|
| | 868 | if(onlyForced && !forced) |
|---|
| | 869 | continue; |
|---|
| | 870 | if(forced) |
|---|
| | 871 | *hasForcedSubtitles = forced; |
|---|
| | 872 | free(extracted); |
|---|
| | 873 | uint32_t startTime = currentSample->timeStamp + startTimestamp; |
|---|
| | 874 | uint32_t endTime = currentSample->timeStamp + endTimestamp; |
|---|
| | 875 | int duration = endTimestamp - startTimestamp; |
|---|
| | 876 | if(duration <= 0) |
|---|
| | 877 | //Skip samples which are broken |
|---|
| | 878 | continue; |
|---|
| | 879 | if(firstSample == nil) |
|---|
| | 880 | { |
|---|
| | 881 | currentSample->timeStamp = startTime; |
|---|
| | 882 | firstSample = currentSample; |
|---|
| | 883 | } |
|---|
| | 884 | else if(lastTime != startTime) |
|---|
| | 885 | { |
|---|
| | 886 | //insert a sample with no real data, to clear the subs |
|---|
| | 887 | memset(sample, 0, sizeof(SampleReference64Record)); |
|---|
| | 888 | sample->durationPerSample = startTime - lastTime; |
|---|
| | 889 | sample->numberOfSamples = 1; |
|---|
| | 890 | sample->dataSize = 1; |
|---|
| | 891 | totalSamples++; |
|---|
| | 892 | sample++; |
|---|
| | 893 | } |
|---|
| | 894 | |
|---|
| | 895 | sample->dataOffset.hi = 0; |
|---|
| | 896 | sample->dataOffset.lo = offset; |
|---|
| | 897 | sample->dataSize = size; |
|---|
| | 898 | sample->sampleFlags = 0; |
|---|
| | 899 | sample->durationPerSample = duration; |
|---|
| | 900 | sample->numberOfSamples = 1; |
|---|
| | 901 | lastTime = endTime; |
|---|
| | 902 | totalSamples++; |
|---|
| | 903 | sample++; |
|---|
| | 904 | } |
|---|
| | 905 | AddMediaSampleReferences64(trackMedia, (SampleDescriptionHandle)imgDesc, totalSamples, samples, NULL); |
|---|
| | 906 | free(samples); |
|---|
| | 907 | NSString *langStr = track->language; |
|---|
| | 908 | int lang = langUnspecified; |
|---|
| | 909 | if([langStr length] == 3) |
|---|
| | 910 | { |
|---|
| | 911 | char langCStr[4] = ""; |
|---|
| | 912 | |
|---|
| | 913 | CFStringGetCString((CFStringRef)langStr, langCStr, 4, kCFStringEncodingASCII); |
|---|
| | 914 | lang = ISO639_2ToQTLangCode(langCStr); |
|---|
| | 915 | } |
|---|
| | 916 | else if([langStr length] == 2) |
|---|
| | 917 | { |
|---|
| | 918 | char langCStr[3] = ""; |
|---|
| | 919 | |
|---|
| | 920 | CFStringGetCString((CFStringRef)langStr, langCStr, 3, kCFStringEncodingASCII); |
|---|
| | 921 | lang = ISO639_1ToQTLangCode(langCStr); |
|---|
| | 922 | } |
|---|
| | 923 | SetMediaLanguage(trackMedia, lang); |
|---|
| | 924 | |
|---|
| | 925 | TimeValue mediaDuration = GetMediaDuration(trackMedia); |
|---|
| | 926 | TimeValue movieTimeScale = GetMovieTimeScale(info.theMovie); |
|---|
| | 927 | *theTrack = GetMediaTrack(trackMedia); |
|---|
| | 928 | if(firstSample == nil) |
|---|
| | 929 | firstSample = [track->samples objectAtIndex:0]; |
|---|
| | 930 | return InsertMediaIntoTrack(*theTrack, (firstSample->timeStamp * movieTimeScale)/1000, 0, mediaDuration, fixed1); |
|---|
| | 931 | } |
|---|
| 943 | | int sampleCount = [track->samples count]; |
|---|
| 944 | | int totalSamples = sampleCount; |
|---|
| 945 | | SampleReference64Ptr samples = (SampleReference64Ptr)calloc(sampleCount*2, sizeof(SampleReference64Record)); |
|---|
| 946 | | SampleReference64Ptr sample = samples; |
|---|
| 947 | | int i; |
|---|
| 948 | | uint32_t lastTime = 0; |
|---|
| 949 | | for(i=0; i<sampleCount; i++) |
|---|
| 950 | | { |
|---|
| 951 | | VobSubSample *currentSample = [track->samples objectAtIndex:i]; |
|---|
| 952 | | int offset = currentSample->fileOffset; |
|---|
| 953 | | int nextOffset; |
|---|
| 954 | | if(i == sampleCount - 1) |
|---|
| 955 | | nextOffset = subFileSize; |
|---|
| 956 | | else |
|---|
| 957 | | nextOffset = ((VobSubSample *)[track->samples objectAtIndex:i+1])->fileOffset; |
|---|
| 958 | | int size = nextOffset - offset; |
|---|
| 959 | | if(size < 0) |
|---|
| 960 | | //Skip samples for which we cannot determine size |
|---|
| 961 | | continue; |
|---|
| 962 | | |
|---|
| 963 | | NSData *subData = [subFileData subdataWithRange:NSMakeRange(offset, size)]; |
|---|
| 964 | | uint8_t *extracted = (uint8_t *)malloc(size); |
|---|
| 965 | | int extractedSize = ExtractVobSubPacket(extracted, (const UInt8 *)[subData bytes], size, &size); |
|---|
| 966 | | |
|---|
| 967 | | uint16_t startTimestamp, endTimestamp; |
|---|
| 968 | | ReadPacketTimes(extracted, extractedSize, &startTimestamp, &endTimestamp); |
|---|
| 969 | | free(extracted); |
|---|
| 970 | | uint32_t startTime = currentSample->timeStamp + startTimestamp; |
|---|
| 971 | | uint32_t endTime = currentSample->timeStamp + endTimestamp; |
|---|
| 972 | | int duration = endTimestamp - startTimestamp; |
|---|
| 973 | | if(duration <= 0) |
|---|
| 974 | | //Skip samples which are broken |
|---|
| 975 | | continue; |
|---|
| 976 | | if(i == 0) |
|---|
| 977 | | currentSample->timeStamp = startTime; |
|---|
| 978 | | else if(lastTime != startTime) |
|---|
| 979 | | { |
|---|
| 980 | | //insert a sample with no real data, to clear the subs |
|---|
| 981 | | memset(sample, 0, sizeof(SampleReference64Record)); |
|---|
| 982 | | sample->durationPerSample = startTime - lastTime; |
|---|
| 983 | | sample->numberOfSamples = 1; |
|---|
| 984 | | sample->dataSize = 1; |
|---|
| 985 | | totalSamples++; |
|---|
| 986 | | sample++; |
|---|
| 987 | | } |
|---|
| 988 | | |
|---|
| 989 | | sample->dataOffset.hi = 0; |
|---|
| 990 | | sample->dataOffset.lo = offset; |
|---|
| 991 | | sample->dataSize = size; |
|---|
| 992 | | sample->sampleFlags = 0; |
|---|
| 993 | | sample->durationPerSample = duration; |
|---|
| 994 | | sample->numberOfSamples = 1; |
|---|
| 995 | | lastTime = endTime; |
|---|
| 996 | | |
|---|
| 997 | | sample++; |
|---|
| 998 | | } |
|---|
| 999 | | AddMediaSampleReferences64(trackMedia, (SampleDescriptionHandle)imgDesc, totalSamples, samples, NULL); |
|---|
| 1000 | | free(samples); |
|---|
| 1001 | | NSString *langStr = track->language; |
|---|
| 1002 | | int lang = langUnspecified; |
|---|
| 1003 | | if([langStr length] == 3) |
|---|
| 1004 | | { |
|---|
| 1005 | | char langCStr[4] = ""; |
|---|
| 1006 | | |
|---|
| 1007 | | CFStringGetCString((CFStringRef)langStr, langCStr, 4, kCFStringEncodingASCII); |
|---|
| 1008 | | lang = ISO639_2ToQTLangCode(langCStr); |
|---|
| 1009 | | } |
|---|
| 1010 | | else if([langStr length] == 2) |
|---|
| 1011 | | { |
|---|
| 1012 | | char langCStr[3] = ""; |
|---|
| 1013 | | |
|---|
| 1014 | | CFStringGetCString((CFStringRef)langStr, langCStr, 3, kCFStringEncodingASCII); |
|---|
| 1015 | | lang = ISO639_1ToQTLangCode(langCStr); |
|---|
| 1016 | | } |
|---|
| 1017 | | SetMediaLanguage(trackMedia, lang); |
|---|
| 1018 | | |
|---|
| 1019 | | TimeValue mediaDuration = GetMediaDuration(trackMedia); |
|---|
| 1020 | | TimeValue movieTimeScale = GetMovieTimeScale(theMovie); |
|---|
| 1021 | | Track theTrack = GetMediaTrack(trackMedia); |
|---|
| 1022 | | VobSubSample *firstSample = [track->samples objectAtIndex:0]; |
|---|
| 1023 | | err = InsertMediaIntoTrack(theTrack, (firstSample->timeStamp * movieTimeScale)/1000, 0, mediaDuration, fixed1); |
|---|