comparison mpeg.c @ 346:e154eb1b7149 libavformat

caching of timestamps for mpeg-ps so seeking is faster move (av_)find_stream_index() to utils.c as its usefull outside mpeg.c assert checking enabled, to find bugs quicker, should obviously be disabled later (av_)add_index_entry() inserts new entries so that the list stays ordered and updates entries if already in it (av_)index_search_timestamp() cleanup (kill ugly goto) and shorter
author michael
date Tue, 13 Jan 2004 22:02:49 +0000
parents f6b2b0718235
children 6770ca07abe2
comparison
equal deleted inserted replaced
345:d94c6fd7b95e 346:e154eb1b7149
18 */ 18 */
19 #include "avformat.h" 19 #include "avformat.h"
20 20
21 #define MAX_PAYLOAD_SIZE 4096 21 #define MAX_PAYLOAD_SIZE 4096
22 //#define DEBUG_SEEK 22 //#define DEBUG_SEEK
23
24 #undef NDEBUG
25 #include <assert.h>
23 26
24 typedef struct { 27 typedef struct {
25 uint8_t buffer[MAX_PAYLOAD_SIZE]; 28 uint8_t buffer[MAX_PAYLOAD_SIZE];
26 int buffer_ptr; 29 int buffer_ptr;
27 int nb_frames; /* number of starting frame encountered (AC3) */ 30 int nb_frames; /* number of starting frame encountered (AC3) */
900 get_byte(&s->pb); 903 get_byte(&s->pb);
901 get_byte(&s->pb); 904 get_byte(&s->pb);
902 len -= 3; 905 len -= 3;
903 } 906 }
904 } 907 }
908 if(dts != AV_NOPTS_VALUE && ppos){
909 int i;
910 for(i=0; i<s->nb_streams; i++){
911 if(startcode == s->streams[i]->id) {
912 av_add_index_entry(s->streams[i], *ppos, dts, 0 /* FIXME keyframe? */);
913 }
914 }
915 }
916
905 *pstart_code = startcode; 917 *pstart_code = startcode;
906 *ppts = pts; 918 *ppts = pts;
907 *pdts = dts; 919 *pdts = dts;
908 return len; 920 return len;
909 } 921 }
911 static int mpegps_read_packet(AVFormatContext *s, 923 static int mpegps_read_packet(AVFormatContext *s,
912 AVPacket *pkt) 924 AVPacket *pkt)
913 { 925 {
914 AVStream *st; 926 AVStream *st;
915 int len, startcode, i, type, codec_id; 927 int len, startcode, i, type, codec_id;
916 int64_t pts, dts; 928 int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work
917 929
918 redo: 930 redo:
919 len = mpegps_read_pes_header(s, NULL, &startcode, &pts, &dts, 1); 931 len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts, 1);
920 if (len < 0) 932 if (len < 0)
921 return len; 933 return len;
922 934
923 /* now find stream */ 935 /* now find stream */
924 for(i=0;i<s->nb_streams;i++) { 936 for(i=0;i<s->nb_streams;i++) {
1020 #endif 1032 #endif
1021 *ppos = pos; 1033 *ppos = pos;
1022 return dts; 1034 return dts;
1023 } 1035 }
1024 1036
1025 static int find_stream_index(AVFormatContext *s)
1026 {
1027 int i;
1028 AVStream *st;
1029
1030 if (s->nb_streams <= 0)
1031 return -1;
1032 for(i = 0; i < s->nb_streams; i++) {
1033 st = s->streams[i];
1034 if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
1035 return i;
1036 }
1037 }
1038 return 0;
1039 }
1040
1041 static int mpegps_read_seek(AVFormatContext *s, 1037 static int mpegps_read_seek(AVFormatContext *s,
1042 int stream_index, int64_t timestamp) 1038 int stream_index, int64_t timestamp)
1043 { 1039 {
1044 int64_t pos_min, pos_max, pos; 1040 int64_t pos_min, pos_max, pos;
1045 int64_t dts_min, dts_max, dts; 1041 int64_t dts_min, dts_max, dts;
1042 int index;
1043 AVStream *st;
1046 1044
1047 timestamp = (timestamp * 90000) / AV_TIME_BASE; 1045 timestamp = (timestamp * 90000) / AV_TIME_BASE;
1048 1046
1049 #ifdef DEBUG_SEEK 1047 #ifdef DEBUG_SEEK
1050 printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0); 1048 printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0);
1051 #endif 1049 #endif
1052 1050
1053 /* XXX: find stream_index by looking at the first PES packet found */ 1051 /* XXX: find stream_index by looking at the first PES packet found */
1054 if (stream_index < 0) { 1052 if (stream_index < 0) {
1055 stream_index = find_stream_index(s); 1053 stream_index = av_find_default_stream_index(s);
1056 if (stream_index < 0) 1054 if (stream_index < 0)
1057 return -1; 1055 return -1;
1058 } 1056 }
1059 pos_min = 0; 1057
1060 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); 1058 dts_max=
1061 if (dts_min == AV_NOPTS_VALUE) { 1059 dts_min= AV_NOPTS_VALUE;
1062 /* we can reach this case only if no PTS are present in 1060
1063 the whole stream */ 1061 st= s->streams[stream_index];
1064 return -1; 1062 if(st->index_entries){
1065 } 1063 AVIndexEntry *e;
1066 pos_max = url_filesize(url_fileno(&s->pb)) - 1; 1064
1067 dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0); 1065 index= av_index_search_timestamp(st, timestamp);
1066 e= &st->index_entries[index];
1067 if(e->timestamp <= timestamp){
1068 pos_min= e->pos;
1069 dts_min= e->timestamp;
1070 #ifdef DEBUG_SEEK
1071 printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n",
1072 pos_min,dts_min / 90000.0);
1073 #endif
1074 }else{
1075 assert(index==0);
1076 }
1077 index++;
1078 if(index < st->nb_index_entries){
1079 e= &st->index_entries[index];
1080 assert(e->timestamp >= timestamp);
1081 pos_max= e->pos;
1082 dts_max= e->timestamp;
1083 #ifdef DEBUG_SEEK
1084 printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n",
1085 pos_max,dts_max / 90000.0);
1086 #endif
1087 }
1088 }
1089
1090 if(dts_min == AV_NOPTS_VALUE){
1091 pos_min = 0;
1092 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1);
1093 if (dts_min == AV_NOPTS_VALUE) {
1094 /* we can reach this case only if no PTS are present in
1095 the whole stream */
1096 return -1;
1097 }
1098 }
1099 if(dts_max == AV_NOPTS_VALUE){
1100 pos_max = url_filesize(url_fileno(&s->pb)) - 1;
1101 dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0);
1102 }
1068 1103
1069 while (pos_min <= pos_max) { 1104 while (pos_min <= pos_max) {
1070 #ifdef DEBUG_SEEK 1105 #ifdef DEBUG_SEEK
1071 printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n", 1106 printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n",
1072 pos_min, pos_max, 1107 pos_min, pos_max,