Mercurial > libavformat.hg
comparison mpegts.c @ 4966:a6c807c154b1 libavformat
return error in mpegts_push_data and propagate it
author | bcoudurier |
---|---|
date | Wed, 27 May 2009 00:56:31 +0000 |
parents | ca59375d99f8 |
children | 1d10f8b761b7 |
comparison
equal
deleted
inserted
replaced
4965:ca59375d99f8 | 4966:a6c807c154b1 |
---|---|
49 MPEGTS_SECTION, | 49 MPEGTS_SECTION, |
50 }; | 50 }; |
51 | 51 |
52 typedef struct MpegTSFilter MpegTSFilter; | 52 typedef struct MpegTSFilter MpegTSFilter; |
53 | 53 |
54 typedef void PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos); | 54 typedef int PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos); |
55 | 55 |
56 typedef struct MpegTSPESFilter { | 56 typedef struct MpegTSPESFilter { |
57 PESCallback *pes_cb; | 57 PESCallback *pes_cb; |
58 void *opaque; | 58 void *opaque; |
59 } MpegTSPESFilter; | 59 } MpegTSPESFilter; |
825 pes->buffer = NULL; | 825 pes->buffer = NULL; |
826 pes->data_index = 0; | 826 pes->data_index = 0; |
827 } | 827 } |
828 | 828 |
829 /* return non zero if a packet could be constructed */ | 829 /* return non zero if a packet could be constructed */ |
830 static void mpegts_push_data(MpegTSFilter *filter, | 830 static int mpegts_push_data(MpegTSFilter *filter, |
831 const uint8_t *buf, int buf_size, int is_start, | 831 const uint8_t *buf, int buf_size, int is_start, |
832 int64_t pos) | 832 int64_t pos) |
833 { | 833 { |
834 PESContext *pes = filter->u.pes_filter.opaque; | 834 PESContext *pes = filter->u.pes_filter.opaque; |
835 MpegTSContext *ts = pes->ts; | 835 MpegTSContext *ts = pes->ts; |
836 const uint8_t *p; | 836 const uint8_t *p; |
837 int len, code; | 837 int len, code; |
838 | 838 |
839 if(!ts->pkt) | 839 if(!ts->pkt) |
840 return; | 840 return 0; |
841 | 841 |
842 if (is_start) { | 842 if (is_start) { |
843 if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { | 843 if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { |
844 new_pes_packet(pes, ts->pkt); | 844 new_pes_packet(pes, ts->pkt); |
845 ts->stop_parse = 1; | 845 ts->stop_parse = 1; |
891 /**********************************************/ | 891 /**********************************************/ |
892 /* PES packing parsing */ | 892 /* PES packing parsing */ |
893 case MPEGTS_PESHEADER_FILL: | 893 case MPEGTS_PESHEADER_FILL: |
894 len = pes->pes_header_size - pes->data_index; | 894 len = pes->pes_header_size - pes->data_index; |
895 if (len < 0) | 895 if (len < 0) |
896 return; | 896 return -1; |
897 if (len > buf_size) | 897 if (len > buf_size) |
898 len = buf_size; | 898 len = buf_size; |
899 memcpy(pes->header + pes->data_index, p, len); | 899 memcpy(pes->header + pes->data_index, p, len); |
900 pes->data_index += len; | 900 pes->data_index += len; |
901 p += len; | 901 p += len; |
923 else | 923 else |
924 pes->total_size = MAX_PES_PAYLOAD; | 924 pes->total_size = MAX_PES_PAYLOAD; |
925 /* allocate pes buffer */ | 925 /* allocate pes buffer */ |
926 pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); | 926 pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); |
927 if (!pes->buffer) | 927 if (!pes->buffer) |
928 return; | 928 return AVERROR(ENOMEM); |
929 | 929 |
930 /* we got the full header. We parse it and get the payload */ | 930 /* we got the full header. We parse it and get the payload */ |
931 pes->state = MPEGTS_PAYLOAD; | 931 pes->state = MPEGTS_PAYLOAD; |
932 pes->data_index = 0; | 932 pes->data_index = 0; |
933 } | 933 } |
937 if (pes->data_index+buf_size > pes->total_size) { | 937 if (pes->data_index+buf_size > pes->total_size) { |
938 new_pes_packet(pes, ts->pkt); | 938 new_pes_packet(pes, ts->pkt); |
939 pes->total_size = MAX_PES_PAYLOAD; | 939 pes->total_size = MAX_PES_PAYLOAD; |
940 pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); | 940 pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); |
941 if (!pes->buffer) | 941 if (!pes->buffer) |
942 return; | 942 return AVERROR(ENOMEM); |
943 ts->stop_parse = 1; | 943 ts->stop_parse = 1; |
944 } | 944 } |
945 memcpy(pes->buffer+pes->data_index, p, buf_size); | 945 memcpy(pes->buffer+pes->data_index, p, buf_size); |
946 pes->data_index += buf_size; | 946 pes->data_index += buf_size; |
947 } | 947 } |
950 case MPEGTS_SKIP: | 950 case MPEGTS_SKIP: |
951 buf_size = 0; | 951 buf_size = 0; |
952 break; | 952 break; |
953 } | 953 } |
954 } | 954 } |
955 | |
956 return 0; | |
955 } | 957 } |
956 | 958 |
957 static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code) | 959 static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code) |
958 { | 960 { |
959 AVStream *st; | 961 AVStream *st; |
1051 } | 1053 } |
1052 return pes; | 1054 return pes; |
1053 } | 1055 } |
1054 | 1056 |
1055 /* handle one TS packet */ | 1057 /* handle one TS packet */ |
1056 static void handle_packet(MpegTSContext *ts, const uint8_t *packet) | 1058 static int handle_packet(MpegTSContext *ts, const uint8_t *packet) |
1057 { | 1059 { |
1058 AVFormatContext *s = ts->stream; | 1060 AVFormatContext *s = ts->stream; |
1059 MpegTSFilter *tss; | 1061 MpegTSFilter *tss; |
1060 int len, pid, cc, cc_ok, afc, is_start; | 1062 int len, pid, cc, cc_ok, afc, is_start; |
1061 const uint8_t *p, *p_end; | 1063 const uint8_t *p, *p_end; |
1062 int64_t pos; | 1064 int64_t pos; |
1063 | 1065 |
1064 pid = AV_RB16(packet + 1) & 0x1fff; | 1066 pid = AV_RB16(packet + 1) & 0x1fff; |
1065 if(pid && discard_pid(ts, pid)) | 1067 if(pid && discard_pid(ts, pid)) |
1066 return; | 1068 return 0; |
1067 is_start = packet[1] & 0x40; | 1069 is_start = packet[1] & 0x40; |
1068 tss = ts->pids[pid]; | 1070 tss = ts->pids[pid]; |
1069 if (ts->auto_guess && tss == NULL && is_start) { | 1071 if (ts->auto_guess && tss == NULL && is_start) { |
1070 add_pes_stream(ts, pid, -1, 0); | 1072 add_pes_stream(ts, pid, -1, 0); |
1071 tss = ts->pids[pid]; | 1073 tss = ts->pids[pid]; |
1072 } | 1074 } |
1073 if (!tss) | 1075 if (!tss) |
1074 return; | 1076 return 0; |
1075 | 1077 |
1076 /* continuity check (currently not used) */ | 1078 /* continuity check (currently not used) */ |
1077 cc = (packet[3] & 0xf); | 1079 cc = (packet[3] & 0xf); |
1078 cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); | 1080 cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); |
1079 tss->last_cc = cc; | 1081 tss->last_cc = cc; |
1080 | 1082 |
1081 /* skip adaptation field */ | 1083 /* skip adaptation field */ |
1082 afc = (packet[3] >> 4) & 3; | 1084 afc = (packet[3] >> 4) & 3; |
1083 p = packet + 4; | 1085 p = packet + 4; |
1084 if (afc == 0) /* reserved value */ | 1086 if (afc == 0) /* reserved value */ |
1085 return; | 1087 return 0; |
1086 if (afc == 2) /* adaptation field only */ | 1088 if (afc == 2) /* adaptation field only */ |
1087 return; | 1089 return 0; |
1088 if (afc == 3) { | 1090 if (afc == 3) { |
1089 /* skip adapation field */ | 1091 /* skip adapation field */ |
1090 p += p[0] + 1; | 1092 p += p[0] + 1; |
1091 } | 1093 } |
1092 /* if past the end of packet, ignore */ | 1094 /* if past the end of packet, ignore */ |
1093 p_end = packet + TS_PACKET_SIZE; | 1095 p_end = packet + TS_PACKET_SIZE; |
1094 if (p >= p_end) | 1096 if (p >= p_end) |
1095 return; | 1097 return 0; |
1096 | 1098 |
1097 pos = url_ftell(ts->stream->pb); | 1099 pos = url_ftell(ts->stream->pb); |
1098 ts->pos47= pos % ts->raw_packet_size; | 1100 ts->pos47= pos % ts->raw_packet_size; |
1099 | 1101 |
1100 if (tss->type == MPEGTS_SECTION) { | 1102 if (tss->type == MPEGTS_SECTION) { |
1101 if (is_start) { | 1103 if (is_start) { |
1102 /* pointer field present */ | 1104 /* pointer field present */ |
1103 len = *p++; | 1105 len = *p++; |
1104 if (p + len > p_end) | 1106 if (p + len > p_end) |
1105 return; | 1107 return 0; |
1106 if (len && cc_ok) { | 1108 if (len && cc_ok) { |
1107 /* write remaining section bytes */ | 1109 /* write remaining section bytes */ |
1108 write_section_data(s, tss, | 1110 write_section_data(s, tss, |
1109 p, len, 0); | 1111 p, len, 0); |
1110 /* check whether filter has been closed */ | 1112 /* check whether filter has been closed */ |
1111 if (!ts->pids[pid]) | 1113 if (!ts->pids[pid]) |
1112 return; | 1114 return 0; |
1113 } | 1115 } |
1114 p += len; | 1116 p += len; |
1115 if (p < p_end) { | 1117 if (p < p_end) { |
1116 write_section_data(s, tss, | 1118 write_section_data(s, tss, |
1117 p, p_end - p, 1); | 1119 p, p_end - p, 1); |
1121 write_section_data(s, tss, | 1123 write_section_data(s, tss, |
1122 p, p_end - p, 0); | 1124 p, p_end - p, 0); |
1123 } | 1125 } |
1124 } | 1126 } |
1125 } else { | 1127 } else { |
1128 int ret; | |
1126 // Note: The position here points actually behind the current packet. | 1129 // Note: The position here points actually behind the current packet. |
1127 tss->u.pes_filter.pes_cb(tss, | 1130 if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, |
1128 p, p_end - p, is_start, pos - ts->raw_packet_size); | 1131 pos - ts->raw_packet_size)) < 0) |
1129 } | 1132 return ret; |
1133 } | |
1134 | |
1135 return 0; | |
1130 } | 1136 } |
1131 | 1137 |
1132 /* XXX: try to find a better synchro over several packets (use | 1138 /* XXX: try to find a better synchro over several packets (use |
1133 get_packet_size() ?) */ | 1139 get_packet_size() ?) */ |
1134 static int mpegts_resync(ByteIOContext *pb) | 1140 static int mpegts_resync(ByteIOContext *pb) |
1191 if (nb_packets != 0 && packet_num >= nb_packets) | 1197 if (nb_packets != 0 && packet_num >= nb_packets) |
1192 break; | 1198 break; |
1193 ret = read_packet(pb, packet, ts->raw_packet_size); | 1199 ret = read_packet(pb, packet, ts->raw_packet_size); |
1194 if (ret != 0) | 1200 if (ret != 0) |
1195 return ret; | 1201 return ret; |
1196 handle_packet(ts, packet); | 1202 ret = handle_packet(ts, packet); |
1203 if (ret != 0) | |
1204 return ret; | |
1197 } | 1205 } |
1198 return 0; | 1206 return 0; |
1199 } | 1207 } |
1200 | 1208 |
1201 static int mpegts_probe(AVProbeData *p) | 1209 static int mpegts_probe(AVProbeData *p) |