comparison libmpdemux/muxer_mpeg.c @ 18192:0b77e66a7d32

introduced new functions to handle pack writing and interleaving strategy (will soon replace current ones)
author nicodvb
date Sat, 22 Apr 2006 15:41:16 +0000
parents 7d83cd632b6b
children f7f6984638f8
comparison
equal deleted inserted replaced
18191:0b8ca8721411 18192:0b77e66a7d32
986 spriv->framebuf[i] = tmp; 986 spriv->framebuf[i] = tmp;
987 } 987 }
988 spriv->framebuf_used -= n; 988 spriv->framebuf_used -= n;
989 } 989 }
990 990
991 static int calc_packet_len(muxer_stream_t *s, int psize, int finalize)
992 {
993 muxer_headers_t *spriv = s->priv;
994 int n, len, frpos, m;
995
996 n = len = 0;
997 frpos = spriv->framebuf[0].pos;
998 while(len < psize && n < spriv->framebuf_used)
999 {
1000 if(!frpos && len>0 && s->type == MUXER_TYPE_VIDEO && spriv->framebuf[n].type==I_FRAME)
1001 return len;
1002 m = min(spriv->framebuf[n].size - frpos, psize - len);
1003 len += m;
1004 frpos += m;
1005 if(frpos == spriv->framebuf[n].size)
1006 {
1007 frpos = 0;
1008 n++;
1009 }
1010 }
1011
1012 if(len < psize && !finalize)
1013 return 0;
1014 return len;
1015 }
1016
1017 static int find_packet_timestamps(muxer_priv_t *priv, muxer_stream_t *s, uint64_t *dts, uint64_t *pts)
1018 {
1019 muxer_headers_t *spriv = s->priv;
1020 int i, m, pes_hlen, ret, threshold;
1021 uint64_t spts, sdts, dpts;
1022
1023 if(!spriv->framebuf_used)
1024 return 0;
1025
1026 spts = spriv->pts;
1027 sdts = spriv->dts;
1028 spriv->dts = spriv->pts = 0;
1029 ret = 0;
1030 if(spriv->framebuf[0].pos == 0) // start of frame
1031 i = 0;
1032 else
1033 {
1034 pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);
1035
1036 if(pes_hlen < spriv->min_pes_hlen)
1037 pes_hlen = spriv->min_pes_hlen;
1038
1039 m = spriv->framebuf[0].size - spriv->framebuf[0].pos;
1040
1041 if(spriv->pack_offset + pes_hlen + m >= priv->packet_size)
1042 i = -1; //this pack won't have a pts: no space available
1043 else
1044 {
1045 if(spriv->framebuf_used < 2)
1046 goto fail;
1047
1048 if(spriv->framebuf[1].pts == spriv->framebuf[1].dts)
1049 threshold = 5;
1050 else
1051 threshold = 10;
1052
1053 //headers+frame 0 < space available including timestamps
1054 if(spriv->pack_offset + pes_hlen + m < priv->packet_size - threshold)
1055 i = 1;
1056 else
1057 i = -1;
1058 }
1059 }
1060
1061 if(i > -1)
1062 {
1063 dpts = max(spriv->last_saved_pts, spriv->framebuf[i].pts) -
1064 min(spriv->last_saved_pts, spriv->framebuf[i].pts) +
1065 spriv->framebuf[0].idur;
1066
1067 if(s->type != MUXER_TYPE_VIDEO)
1068 ret = 1;
1069 else if((spriv->framebuf[i].type == I_FRAME || priv->ts_allframes || dpts >= 45000*300)) //0.5 seconds
1070 ret = 1;
1071
1072 if(ret)
1073 {
1074 *pts = spriv->framebuf[i].pts;
1075 *dts = spriv->framebuf[i].dts;
1076 if(*dts == *pts)
1077 *dts = 0;
1078 //spriv->last_saved_pts = spriv->pts;
1079 }
1080 }
1081
1082 fail:
1083 spriv->pts = spts;
1084 spriv->dts = sdts;
1085 return ret;
1086 }
1087
1088
1089 static int fill_packet(muxer_t *muxer, muxer_stream_t *s, int finalize)
1090 {
1091 //try to fill a packet as much as possible
1092 //spriv->pack_offset is the start position inited to 0
1093 //data is taken from spriv->framebuf
1094 //if audio and a52 insert the headers
1095 muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
1096 muxer_headers_t *spriv = (muxer_headers_t *) s->priv;
1097 int pes_hlen = 0, len, stflen, stuffing_len, i, m, n, testlen, frpos, dvd_pack = 0, len2, target, hlen;
1098 uint64_t spts, sdts, pts=0, dts=0;
1099 mpeg_frame_t *frm;
1100
1101 spts = spriv->pts;
1102 sdts = spriv->dts;
1103
1104 if(! spriv->framebuf_used)
1105 {
1106 spriv->pack_offset = 0;
1107 return 0;
1108 }
1109
1110 if(!spriv->pack_offset)
1111 {
1112 spriv->pack_offset = write_mpeg_pack_header(muxer, spriv->pack);
1113 if(priv->update_system_header && (priv->is_genmpeg1 || priv->is_genmpeg2))
1114 {
1115 spriv->pack_offset += write_mpeg_system_header(muxer, &spriv->pack[spriv->pack_offset]);
1116 priv->update_system_header = 0;
1117 }
1118 spriv->pes_set = 0;
1119 spriv->pes_offset = spriv->pack_offset;
1120 spriv->payload_offset = 0;
1121 spriv->frames = 0;
1122 spriv->last_frame_rest = 0;
1123 }
1124
1125 if(!spriv->pes_set)
1126 {
1127 //search the pts. yes if either it's video && (I-frame or priv->ts_allframes) && framebuf[i].pos == 0
1128 //or it's audio && framebuf[i].pos == 0
1129 //NB pts and dts can only be relative to the first frame beginning in this pack
1130 if((priv->is_xsvcd || priv->is_xvcd) && spriv->size == 0)
1131 spriv->buffer_size = 4*1024;
1132
1133 if(priv->is_dvd && s->type == MUXER_TYPE_VIDEO
1134 && spriv->framebuf[0].type==I_FRAME && spriv->framebuf[0].pos==0)
1135 dvd_pack = 1;
1136
1137 spriv->dts = spriv->pts = 0;
1138 if(find_packet_timestamps(priv, s, &dts, &pts))
1139 {
1140 spriv->pts = pts;
1141 spriv->dts = dts;
1142 spriv->last_saved_pts = pts;
1143 }
1144
1145 pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);
1146 stflen = (spriv->min_pes_hlen > pes_hlen ? spriv->min_pes_hlen - pes_hlen : 0);
1147
1148 target = len = priv->packet_size - spriv->pack_offset - pes_hlen - stflen; //max space available
1149 if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)
1150 hlen = 4;
1151 else
1152 hlen = 0;
1153
1154 len -= hlen;
1155 target -= hlen;
1156
1157 len2 = calc_packet_len(s, target, finalize);
1158 if(!len2)
1159 {
1160 spriv->pack_offset = 0;
1161 return 0;
1162 }
1163 if(len2 < target)
1164 {
1165 if(s->type == MUXER_TYPE_AUDIO && !finalize)
1166 {
1167 spriv->pack_offset = 0;
1168 spriv->pts = spts;
1169 spriv->dts = sdts;
1170 return 0;
1171 }
1172 }
1173 len = len2;
1174 stuffing_len = 0;
1175 if(len < target)
1176 {
1177 if(s->type == MUXER_TYPE_VIDEO) //FIXME: check i_frame
1178 {
1179 if(spriv->pts)
1180 target += 5;
1181 if(spriv->dts)
1182 target += 5;
1183 spriv->pts = spriv->dts = 0;
1184 }
1185
1186 stuffing_len = target - len;
1187 if(stuffing_len > 0 && stuffing_len < 7)
1188 {
1189 if(stflen + stuffing_len > 16)
1190 {
1191 int x = 7 - stuffing_len;
1192 stflen -= x;
1193 stuffing_len += x;
1194
1195 /*int x = stflen + stuffing_len;
1196 stflen = 16;
1197 stuffing_len = x - stflen;
1198 */
1199 }
1200 else
1201 {
1202 stflen += stuffing_len;
1203 stuffing_len = 0;
1204 }
1205 }
1206 }
1207
1208 len += hlen;
1209 spriv->pack_offset += write_mpeg_pes_header(spriv, (uint8_t *) &s->ckid, &(spriv->pack[spriv->pack_offset]),
1210 len, stflen, priv->mux);
1211
1212 if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)
1213 {
1214 spriv->payload_offset = spriv->pack_offset;
1215 spriv->pack_offset += 4; //for the 4 bytes of header
1216 if(!spriv->framebuf[0].pos)
1217 spriv->last_frame_rest = 0;
1218 else
1219 spriv->last_frame_rest = spriv->framebuf[0].size - spriv->framebuf[0].pos;
1220 }
1221
1222 spriv->pes_set = 1;
1223 }
1224
1225
1226 if(spriv->dts || spriv->pts)
1227 {
1228 if((spriv->dts && priv->scr >= spriv->dts) || priv->scr >= spriv->pts)
1229 mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nERROR: scr %.3lf, dts %.3lf, pts %.3lf\r\n", (double) priv->scr/27000000.0, (double) spriv->dts/27000000.0, (double) spriv->pts/27000000.0);
1230 else if(priv->scr + 63000*300 < spriv->dts)
1231 mp_msg(MSGT_MUXER, MSGL_INFO, "\r\nWARNING>: scr %.3lf, dts %.3lf, pts %.3lf, diff %.3lf, piff %.3lf\r\n", (double) priv->scr/27000000.0, (double) spriv->dts/27000000.0, (double) spriv->pts/27000000.0, (double)(spriv->dts - priv->scr)/27000000.0, (double)(spriv->pts - priv->scr)/27000000.0);
1232 }
1233
1234 n = 0;
1235 len = 0;
1236 testlen = 0;
1237
1238 frm = spriv->framebuf;
1239 while(spriv->pack_offset < priv->packet_size && n < spriv->framebuf_used)
1240 {
1241 if(!frm->pos)
1242 {
1243 //since iframes must always be aligned at block boundaries exit when we find the
1244 //beginning of one in the middle of the flush
1245 if(len > 0 && s->type == MUXER_TYPE_VIDEO && frm->type == I_FRAME)
1246 {
1247 testlen = len;
1248 break;
1249 }
1250 spriv->frames++;
1251 update_demux_bufsize(spriv, frm->dts, frm->size, s->type);
1252 }
1253
1254 m = min(frm->size - frm->pos, priv->packet_size - spriv->pack_offset);
1255 memcpy(&(spriv->pack[spriv->pack_offset]), &(frm->buffer[frm->pos]), m);
1256
1257 len += m;
1258 spriv->pack_offset += m;
1259 frm->pos += m;
1260
1261 if(frm->pos == frm->size) //end of frame
1262 {
1263 frm->pos = frm->size = 0;
1264 frm->pts = frm->dts = 0;
1265 n++;
1266 frm++;
1267 }
1268 }
1269
1270 if((priv->is_xsvcd || priv->is_xvcd) && spriv->size == 0)
1271 spriv->buffer_size = 0;
1272
1273 spriv->size += len;
1274
1275 if(dvd_pack && (spriv->pack_offset == priv->packet_size))
1276 write_mpeg_pack(muxer, s, muxer->file, NULL, 0, 0); //insert fake Nav Packet
1277
1278 if(n > 0)
1279 remove_frames(spriv, n);
1280
1281 spriv->track_bufsize += len;
1282 if(spriv->track_bufsize > spriv->max_buffer_size)
1283 mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nBUFFER OVERFLOW: %d > %d\r\n", spriv->track_bufsize, spriv->max_buffer_size);
1284
1285 if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)
1286 fix_a52_headers(s);
1287
1288 if(spriv->pack_offset < priv->packet_size) //here finalize is set
1289 {
1290 int diff = priv->packet_size - spriv->pack_offset;
1291 write_pes_padding(&(spriv->pack[spriv->pack_offset]), diff);
1292 spriv->pack_offset += diff;
1293 }
1294
1295 fwrite(spriv->pack, spriv->pack_offset, 1, muxer->file);
1296
1297 priv->headers_size += spriv->pack_offset - len;
1298 priv->data_size += len;
1299 muxer->movi_end += spriv->pack_offset;
1300
1301 spriv->pack_offset = 0;
1302 spriv->pes_set = 0;
1303 spriv->frames = 0;
1304
1305 spriv->pts = spts;
1306 spriv->dts = sdts;
1307
1308 return len;
1309 }
1310
1311 static inline int find_best_stream(muxer_t *muxer)
1312 {
1313 int i, ndts;
1314 uint64_t dts = -1;
1315 muxer_priv_t *priv = muxer->priv;
1316 muxer_headers_t *spriv;
1317
1318 ndts = -1;
1319
1320 //MUST ALWAYS apply: [pd]ts < SCR + 0.7 seconds
1321 //FIXME: find pack_dts and pack_len instead, for the time being the code below is still reasonable
1322 for(i = 0; i < muxer->avih.dwStreams; i++)
1323 {
1324 spriv = muxer->streams[i]->priv;
1325
1326 if(! spriv->framebuf_used || spriv->track_bufsize + priv->packet_size - 20 > spriv->max_buffer_size)
1327 continue;
1328 //59000 ~= 0.7 seconds - max(frame_duration) (<42 ms at 23.976 fps)
1329 if(spriv->framebuf[0].pts > priv->scr + 59000*300)
1330 continue;
1331
1332 if(spriv->framebuf[0].dts <= dts)
1333 {
1334 dts = spriv->framebuf[0].dts;
1335 ndts = i;
1336 }
1337 }
1338
1339 return ndts;
1340 }
1341
991 static void patch_seq(muxer_priv_t *priv, unsigned char *buf) 1342 static void patch_seq(muxer_priv_t *priv, unsigned char *buf)
992 { 1343 {
993 if(priv->vwidth > 0) 1344 if(priv->vwidth > 0)
994 { 1345 {
995 buf[4] = (priv->vwidth >> 4) & 0xff; 1346 buf[4] = (priv->vwidth >> 4) & 0xff;