Mercurial > libavformat.hg
comparison nut.c @ 437:50bae308f71e libavformat
moving nearly identical binary search code from nut/mpeg/asf to utils.c
author | michael |
---|---|
date | Mon, 12 Apr 2004 16:50:03 +0000 |
parents | 145cd93d0c86 |
children | 6635c1e75087 |
comparison
equal
deleted
inserted
replaced
436:dd042d607ec9 | 437:50bae308f71e |
---|---|
1105 | 1105 |
1106 if(flags & FLAG_PTS){ | 1106 if(flags & FLAG_PTS){ |
1107 if(flags & FLAG_FULL_PTS){ | 1107 if(flags & FLAG_FULL_PTS){ |
1108 pts= get_v(bc); | 1108 pts= get_v(bc); |
1109 if(frame_type && key_frame){ | 1109 if(frame_type && key_frame){ |
1110 int64_t av_pts= pts * AV_TIME_BASE * stream->rate_den / stream->rate_num; | |
1110 av_add_index_entry( | 1111 av_add_index_entry( |
1111 s->streams[stream_id], | 1112 s->streams[stream_id], |
1112 frame_start, | 1113 frame_start, |
1113 pts, | 1114 av_pts, |
1114 frame_start - nut->stream[stream_id].last_sync_pos, | 1115 frame_start - nut->stream[stream_id].last_sync_pos, |
1115 AVINDEX_KEYFRAME); | 1116 AVINDEX_KEYFRAME); |
1116 nut->stream[stream_id].last_sync_pos= frame_start; | 1117 nut->stream[stream_id].last_sync_pos= frame_start; |
1117 assert(nut->packet_start == frame_start); | 1118 assert(nut->packet_start == frame_start); |
1118 } | 1119 } |
1229 nut->written_packet_size= -1; | 1230 nut->written_packet_size= -1; |
1230 } | 1231 } |
1231 } | 1232 } |
1232 } | 1233 } |
1233 | 1234 |
1234 static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){ | 1235 static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){ |
1235 NUTContext *nut = s->priv_data; | 1236 NUTContext *nut = s->priv_data; |
1237 StreamContext *stream; | |
1236 ByteIOContext *bc = &s->pb; | 1238 ByteIOContext *bc = &s->pb; |
1237 int64_t pos, pts; | 1239 int64_t pos, pts; |
1238 uint64_t code; | 1240 uint64_t code; |
1239 int frame_code,step, flags, stream_id, i; | 1241 int frame_code,step, flags, stream_id, i; |
1240 av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%lld,%lld)\n", stream_index, *pos_arg, pos_limit); | 1242 av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%lld,%lld)\n", stream_index, *pos_arg, pos_limit); |
1303 if(stream_id==-1) | 1305 if(stream_id==-1) |
1304 stream_id= get_v(bc); | 1306 stream_id= get_v(bc); |
1305 if(stream_id >= s->nb_streams) | 1307 if(stream_id >= s->nb_streams) |
1306 goto resync; | 1308 goto resync; |
1307 | 1309 |
1308 pts= get_v(bc); | 1310 stream= &nut->stream[stream_id]; |
1311 pts= get_v(bc) * AV_TIME_BASE * stream->rate_den / stream->rate_num; | |
1309 | 1312 |
1310 if(flags & FLAG_KEY_FRAME){ | 1313 if(flags & FLAG_KEY_FRAME){ |
1311 av_add_index_entry( | 1314 av_add_index_entry( |
1312 s->streams[stream_id], | 1315 s->streams[stream_id], |
1313 pos, | 1316 pos, |
1334 } | 1337 } |
1335 } | 1338 } |
1336 return AV_NOPTS_VALUE; | 1339 return AV_NOPTS_VALUE; |
1337 } | 1340 } |
1338 | 1341 |
1339 #define DEBUG_SEEK | |
1340 static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){ | 1342 static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){ |
1341 NUTContext *nut = s->priv_data; | 1343 NUTContext *nut = s->priv_data; |
1342 StreamContext *stream; | 1344 int64_t pos; |
1343 int64_t pos_min, pos_max, pos, pos_limit; | 1345 int i; |
1344 int64_t ts_min, ts_max, ts; | 1346 |
1345 int64_t start_pos; | 1347 if(av_seek_frame_binary(s, stream_index, target_ts) < 0) |
1346 int index, no_change,i; | 1348 return -1; |
1347 AVStream *st; | |
1348 | |
1349 if (stream_index < 0) { | |
1350 stream_index = av_find_default_stream_index(s); | |
1351 if (stream_index < 0) | |
1352 return -1; | |
1353 } | |
1354 stream= &nut->stream[stream_index]; | |
1355 target_ts= (av_rescale(target_ts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE; | |
1356 | |
1357 #ifdef DEBUG_SEEK | |
1358 av_log(s, AV_LOG_DEBUG, "read_seek: %d %lld\n", stream_index, target_ts); | |
1359 #endif | |
1360 | |
1361 ts_max= | |
1362 ts_min= AV_NOPTS_VALUE; | |
1363 pos_limit= -1; //gcc falsely says it may be uninitalized | |
1364 | |
1365 st= s->streams[stream_index]; | |
1366 if(st->index_entries){ | |
1367 AVIndexEntry *e; | |
1368 | |
1369 index= av_index_search_timestamp(st, target_ts); | |
1370 e= &st->index_entries[index]; | |
1371 | |
1372 if(e->timestamp <= target_ts || e->pos == e->min_distance){ | |
1373 pos_min= e->pos; | |
1374 ts_min= e->timestamp; | |
1375 #ifdef DEBUG_SEEK | |
1376 av_log(s, AV_LOG_DEBUG, "unsing cached pos_min=0x%llx dts_min=%lld\n", | |
1377 pos_min,ts_min); | |
1378 #endif | |
1379 }else{ | |
1380 assert(index==0); | |
1381 } | |
1382 index++; | |
1383 if(index < st->nb_index_entries){ | |
1384 e= &st->index_entries[index]; | |
1385 assert(e->timestamp >= target_ts); | |
1386 pos_max= e->pos; | |
1387 ts_max= e->timestamp; | |
1388 pos_limit= pos_max - e->min_distance; | |
1389 #ifdef DEBUG_SEEK | |
1390 av_log(s, AV_LOG_DEBUG, "unsing cached pos_max=0x%llx pos_limit=0x%llx dts_max=%lld\n", | |
1391 pos_max,pos_limit, ts_max); | |
1392 #endif | |
1393 } | |
1394 } | |
1395 | |
1396 if(ts_min == AV_NOPTS_VALUE){ | |
1397 pos_min = 0; | |
1398 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); | |
1399 if (ts_min == AV_NOPTS_VALUE) | |
1400 return -1; | |
1401 } | |
1402 | |
1403 if(ts_max == AV_NOPTS_VALUE){ | |
1404 int step= 1024; | |
1405 pos_max = url_filesize(url_fileno(&s->pb)) - 1; | |
1406 do{ | |
1407 pos_max -= step; | |
1408 ts_max = read_timestamp(s, stream_index, &pos_max, pos_max + step); | |
1409 step += step; | |
1410 }while(ts_max == AV_NOPTS_VALUE && pos_max >= step); | |
1411 if (ts_max == AV_NOPTS_VALUE) | |
1412 return -1; | |
1413 | |
1414 for(;;){ | |
1415 int64_t tmp_pos= pos_max + 1; | |
1416 int64_t tmp_ts= read_timestamp(s, stream_index, &tmp_pos, INT64_MAX); | |
1417 if(tmp_ts == AV_NOPTS_VALUE) | |
1418 break; | |
1419 ts_max= tmp_ts; | |
1420 pos_max= tmp_pos; | |
1421 } | |
1422 pos_limit= pos_max; | |
1423 } | |
1424 | |
1425 no_change=0; | |
1426 while (pos_min < pos_limit) { | |
1427 #ifdef DEBUG_SEEK | |
1428 av_log(s, AV_LOG_DEBUG, "pos_min=0x%llx pos_max=0x%llx dts_min=%lld dts_max=%lld\n", | |
1429 pos_min, pos_max, | |
1430 ts_min, ts_max); | |
1431 #endif | |
1432 assert(pos_limit <= pos_max); | |
1433 | |
1434 if(no_change==0){ | |
1435 int64_t approximate_keyframe_distance= pos_max - pos_limit; | |
1436 // interpolate position (better than dichotomy) | |
1437 pos = (int64_t)((double)(pos_max - pos_min) * | |
1438 (double)(target_ts - ts_min) / | |
1439 (double)(ts_max - ts_min)) + pos_min - approximate_keyframe_distance; | |
1440 }else if(no_change==1){ | |
1441 // bisection, if interpolation failed to change min or max pos last time | |
1442 pos = (pos_min + pos_limit)>>1; | |
1443 }else{ | |
1444 // linear search if bisection failed, can only happen if there are very few or no keframes between min/max | |
1445 pos=pos_min; | |
1446 } | |
1447 if(pos <= pos_min) | |
1448 pos= pos_min + 1; | |
1449 else if(pos > pos_limit) | |
1450 pos= pos_limit; | |
1451 start_pos= pos; | |
1452 | |
1453 ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1 | |
1454 if(pos == pos_max) | |
1455 no_change++; | |
1456 else | |
1457 no_change=0; | |
1458 #ifdef DEBUG_SEEK | |
1459 av_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change); | |
1460 #endif | |
1461 assert(ts != AV_NOPTS_VALUE); | |
1462 if (target_ts < ts) { | |
1463 pos_limit = start_pos - 1; | |
1464 pos_max = pos; | |
1465 ts_max = ts; | |
1466 } else { | |
1467 pos_min = pos; | |
1468 ts_min = ts; | |
1469 /* check if we are lucky */ | |
1470 if (target_ts == ts) | |
1471 break; | |
1472 } | |
1473 } | |
1474 | |
1475 pos = pos_min; | |
1476 #ifdef DEBUG_SEEK | |
1477 pos_min = pos; | |
1478 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); | |
1479 pos_min++; | |
1480 ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX); | |
1481 av_log(s, AV_LOG_DEBUG, "pos=0x%llx %lld<=%lld<=%lld\n", | |
1482 pos, ts_min, target_ts, ts_max); | |
1483 #endif | |
1484 /* do the seek */ | |
1485 url_fseek(&s->pb, pos, SEEK_SET); | |
1486 | 1349 |
1487 nut->written_packet_size= -1; | 1350 nut->written_packet_size= -1; |
1351 pos= url_ftell(&s->pb); | |
1488 for(i=0; i<s->nb_streams; i++) | 1352 for(i=0; i<s->nb_streams; i++) |
1489 nut->stream[i].last_sync_pos= pos; | 1353 nut->stream[i].last_sync_pos= pos; |
1490 | 1354 |
1491 return 0; | 1355 return 0; |
1492 } | 1356 } |
1511 nut_probe, | 1375 nut_probe, |
1512 nut_read_header, | 1376 nut_read_header, |
1513 nut_read_packet, | 1377 nut_read_packet, |
1514 nut_read_close, | 1378 nut_read_close, |
1515 nut_read_seek, | 1379 nut_read_seek, |
1380 nut_read_timestamp, | |
1516 .extensions = "nut", | 1381 .extensions = "nut", |
1517 }; | 1382 }; |
1518 | 1383 |
1519 #ifdef CONFIG_ENCODERS | 1384 #ifdef CONFIG_ENCODERS |
1520 static AVOutputFormat nut_oformat = { | 1385 static AVOutputFormat nut_oformat = { |