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)