Mercurial > mplayer.hg
comparison vobsub.c @ 6706:e1428c2c971f
Lots of compatibility fixes for Windows' Vobsub reader.
author | kmkaplan |
---|---|
date | Thu, 11 Jul 2002 18:49:18 +0000 |
parents | f8551f89dd48 |
children | 24f3276523af |
comparison
equal
deleted
inserted
replaced
6705:68506f182491 | 6706:e1428c2c971f |
---|---|
1010 static void | 1010 static void |
1011 create_idx(vobsub_out_t *me, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height) | 1011 create_idx(vobsub_out_t *me, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height) |
1012 { | 1012 { |
1013 int i; | 1013 int i; |
1014 fprintf(me->fidx, | 1014 fprintf(me->fidx, |
1015 "# VobSub index file, v3 (do not modify this line!)\n" | 1015 "# VobSub index file, v7 (do not modify this line!)\n" |
1016 "#\n" | 1016 "#\n" |
1017 "# Generated by MPlayer " VERSION "\n" | 1017 "# Generated by MPlayer " VERSION "\n" |
1018 "# See <URL:http://www.mplayerhq.hu/> for more information about MPlayer\n" | 1018 "# See <URL:http://www.mplayerhq.hu/> for more information about MPlayer\n" |
1019 "# See <URL:http://vobsub.edensrising.com/> for more information about Vobsub\n" | 1019 "# See <URL:http://vobsub.edensrising.com/> for more information about Vobsub\n" |
1020 "#\n" | 1020 "#\n" |
1053 perror("Error: vobsub_out_open subtitle file open failed"); | 1053 perror("Error: vobsub_out_open subtitle file open failed"); |
1054 strcpy(filename, basename); | 1054 strcpy(filename, basename); |
1055 strcat(filename, ".idx"); | 1055 strcat(filename, ".idx"); |
1056 result->fidx = fopen(filename, "a"); | 1056 result->fidx = fopen(filename, "a"); |
1057 if (result->fidx) { | 1057 if (result->fidx) { |
1058 setvbuf(result->fidx, NULL, _IOLBF, 0); | |
1059 if (ftell(result->fidx) == 0) | 1058 if (ftell(result->fidx) == 0) |
1060 create_idx(result, palette, orig_width, orig_height); | 1059 create_idx(result, palette, orig_width, orig_height); |
1061 fprintf(result->fidx, "\nid: %s, index: %u\n", id ? id : "xx", index); | 1060 fprintf(result->fidx, "\nid: %s, index: %u\n", id ? id : "xx", index); |
1061 /* So that we can check the file now */ | |
1062 fflush(result->fidx); | |
1062 } | 1063 } |
1063 else | 1064 else |
1064 perror("Error: vobsub_out_open index file open failed"); | 1065 perror("Error: vobsub_out_open index file open failed"); |
1065 free(filename); | 1066 free(filename); |
1066 } | 1067 } |
1080 } | 1081 } |
1081 | 1082 |
1082 void | 1083 void |
1083 vobsub_out_output(void *me, const unsigned char *packet, int len, double pts) | 1084 vobsub_out_output(void *me, const unsigned char *packet, int len, double pts) |
1084 { | 1085 { |
1086 static double last_pts; | |
1087 static int last_pts_set = 0; | |
1085 vobsub_out_t *vob = (vobsub_out_t*)me; | 1088 vobsub_out_t *vob = (vobsub_out_t*)me; |
1086 if (vob->fsub) { | 1089 if (vob->fsub) { |
1090 /* Windows' Vobsub require that every packet is exactly 2kB long */ | |
1087 unsigned char buffer[2048]; | 1091 unsigned char buffer[2048]; |
1088 if (vob->fidx) { | 1092 unsigned char *p; |
1093 int remain = 2048; | |
1094 /* Do not output twice a line with the same timestamp, this | |
1095 breaks Windows' Vobsub */ | |
1096 if (vob->fidx && (!last_pts_set || last_pts != pts)) { | |
1097 static unsigned int last_h = 9999, last_m = 9999, last_s = 9999, last_ms = 9999; | |
1089 unsigned int h, m, ms; | 1098 unsigned int h, m, ms; |
1090 double s; | 1099 double s; |
1091 s = pts; | 1100 s = pts; |
1092 h = s / 3600; | 1101 h = s / 3600; |
1093 s -= h * 3600; | 1102 s -= h * 3600; |
1094 m = s / 60; | 1103 m = s / 60; |
1095 s -= m * 60; | 1104 s -= m * 60; |
1096 ms = (s - (unsigned int) s) * 1000; | 1105 ms = (s - (unsigned int) s) * 1000; |
1097 if (ms >= 1000) /* prevent overfolws or bad float stuff */ | 1106 if (ms >= 1000) /* prevent overfolws or bad float stuff */ |
1098 ms = 0; | 1107 ms = 0; |
1099 fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", | 1108 if (h != last_h || m != last_m || (unsigned int) s != last_s || ms != last_ms) { |
1100 h, m, (unsigned int) s, ms, ftell(vob->fsub)); | 1109 fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", |
1101 } | 1110 h, m, (unsigned int) s, ms, ftell(vob->fsub)); |
1102 buffer[0] = 0; | 1111 last_h = h; |
1103 buffer[1] = 0; | 1112 last_m = m; |
1104 buffer[2] = 1; | 1113 last_s = (unsigned int) s; |
1105 buffer[3] = 0xbd; | 1114 last_ms = ms; |
1106 buffer[4] = ((9 + len) >> 8) & 0xff; /* length of payload */ | 1115 } |
1107 buffer[5] = (9 + len) & 0xff; | 1116 } |
1108 buffer[6] = 0x80; /* System-2 (.VOB) stream */ | 1117 last_pts = pts; |
1109 buffer[7] = 0x80; /* pts_flags */ | 1118 last_pts_set = 1; |
1110 buffer[8] = 5; /* hdrlen */ | 1119 |
1111 pts *= 90000; | 1120 /* Packet start code: Windows' Vobsub needs this */ |
1112 buffer[9] = 0x21 | (((unsigned long)pts >> 29) & 0x0e); | 1121 p = buffer; |
1113 buffer[10] = ((unsigned long)pts >> 22) & 0xff; | 1122 *p++ = 0; /* 0x00 */ |
1114 buffer[11] = 0x01 | (((unsigned long)pts >> 14) & 0xfe); | 1123 *p++ = 0; |
1115 buffer[12] = ((unsigned long)pts >> 7) & 0xff; | 1124 *p++ = 1; |
1116 buffer[13] = 0x01 | (((unsigned long)pts << 1) & 0xfe); | 1125 *p++ = 0xba; |
1117 buffer[14] = 0x20 | vob->aid; /* aid */ | 1126 *p++ = 0x40; |
1118 if (fwrite(buffer, 15, 1, vob->fsub) != 1 | 1127 memset(p, 0, 9); |
1128 p += 9; | |
1129 { /* Packet */ | |
1130 static unsigned char last_pts[5] = { 0, 0, 0, 0, 0}; | |
1131 unsigned char now_pts[5]; | |
1132 int pts_len, pad_len, datalen = len; | |
1133 pts *= 90000; | |
1134 now_pts[0] = 0x21 | (((unsigned long)pts >> 29) & 0x0e); | |
1135 now_pts[1] = ((unsigned long)pts >> 22) & 0xff; | |
1136 now_pts[2] = 0x01 | (((unsigned long)pts >> 14) & 0xfe); | |
1137 now_pts[3] = ((unsigned long)pts >> 7) & 0xff; | |
1138 now_pts[4] = 0x01 | (((unsigned long)pts << 1) & 0xfe); | |
1139 pts_len = memcmp(last_pts, now_pts, sizeof(now_pts)) ? sizeof(now_pts) : 0; | |
1140 memcpy(last_pts, now_pts, sizeof(now_pts)); | |
1141 | |
1142 datalen += 3; /* Version, PTS_flags, pts_len */ | |
1143 datalen += pts_len; | |
1144 datalen += 1; /* AID */ | |
1145 pad_len = 2048 - (p - buffer) - 4 /* MPEG ID */ - 2 /* payload len */ - datalen; | |
1146 /* XXX - Go figure what should go here! In any case the | |
1147 packet has to be completly filled. If I can fill it | |
1148 with padding (0x000001be) latter I'll do that. But if | |
1149 there is only room for 6 bytes then I can not write a | |
1150 padding packet. So I add some padding in the PTS | |
1151 field. This looks like a dirty kludge. Oh well... */ | |
1152 if (pad_len < 0) { | |
1153 /* Packet is too big. Let's try ommiting the PTS field */ | |
1154 datalen -= pts_len; | |
1155 pts_len = 0; | |
1156 pad_len = 0; | |
1157 } | |
1158 else if (pad_len > 6) | |
1159 pad_len = 0; | |
1160 datalen += pad_len; | |
1161 | |
1162 *p++ = 0; /* 0x0e */ | |
1163 *p++ = 0; | |
1164 *p++ = 1; | |
1165 *p++ = 0xbd; | |
1166 | |
1167 *p++ = (datalen >> 8) & 0xff; /* length of payload */ | |
1168 *p++ = datalen & 0xff; | |
1169 *p++ = 0x80; /* System-2 (.VOB) stream */ | |
1170 *p++ = pts_len ? 0x80 : 0x00; /* pts_flags */ | |
1171 *p++ = pts_len + pad_len; | |
1172 memcpy(p, now_pts, pts_len); | |
1173 p += pts_len; | |
1174 memset(p, 0, pad_len); | |
1175 p += pad_len; | |
1176 } | |
1177 *p++ = 0x20 | vob->aid; /* aid */ | |
1178 if (fwrite(buffer, p - buffer, 1, vob->fsub) != 1 | |
1119 || fwrite(packet, len, 1, vob->fsub) != 1) | 1179 || fwrite(packet, len, 1, vob->fsub) != 1) |
1120 perror("ERROR: vobsub write failed"); | 1180 perror("ERROR: vobsub write failed"); |
1121 /* padding */ | 1181 else |
1122 len = 2048 - 15 - len; | 1182 remain -= p - buffer + len; |
1123 buffer[0] = 0x00; | 1183 |
1124 buffer[1] = 0x00; | 1184 /* Padding */ |
1125 buffer[2] = 0x01; | 1185 if (remain >= 6) { |
1126 buffer[3] = 0xbe; | 1186 p = buffer; |
1127 buffer[4] = (len - 6) >> 8; | 1187 *p++ = 0x00; |
1128 buffer[5] = (len - 6) & 0xff; | 1188 *p++ = 0x00; |
1129 /* for better compression, blank this */ | 1189 *p++ = 0x01; |
1130 memset(buffer + 6, 0, len - 6); | 1190 *p++ = 0xbe; |
1131 if (fwrite(buffer, len, 1, vob->fsub) != 1) | 1191 *p++ = (remain - 6) >> 8; |
1132 perror("ERROR: vobsub padding write failed"); | 1192 *p++ = (remain - 6) & 0xff; |
1133 } | 1193 /* for better compression, blank this */ |
1134 } | 1194 memset(buffer + 6, 0, remain - (p - buffer)); |
1135 | 1195 if (fwrite(buffer, remain, 1, vob->fsub) != 1) |
1196 perror("ERROR: vobsub padding write failed"); | |
1197 } | |
1198 else if (remain > 0) { | |
1199 /* I don't know what to output. But anyway the block | |
1200 needs to be 2KB big */ | |
1201 memset(buffer, 0, remain); | |
1202 if (fwrite(buffer, remain, 1, vob->fsub) != 1) | |
1203 perror("ERROR: vobsub blank padding write failed"); | |
1204 } | |
1205 else if (remain < 0) | |
1206 fprintf(stderr, | |
1207 "\nERROR: wrong thing happenned...\n" | |
1208 " I wrote a %i data bytes spu packet and that's too long\n", len); | |
1209 } | |
1210 } |