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 }