static int qdraw_probe(AVProbeData *p) { const uint8_t *b = p->buf; if ( p->buf_size >= 528 && (AV_RB64(b + 520) & 0xFFFFFFFFFFFF) == 0x001102ff0c00 && AV_RB16(b + 520) && AV_RB16(b + 518)) return AVPROBE_SCORE_MAX * 3 / 4; if ( (AV_RB64(b + 8) & 0xFFFFFFFFFFFF) == 0x001102ff0c00 && AV_RB16(b + 8) && AV_RB16(b + 6)) return AVPROBE_SCORE_EXTENSION / 4; return 0; }
static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) { unsigned int size; char buf[1024]; if (data >= data_end) return; switch (*data++) { case AMF_DATA_TYPE_NUMBER: av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2dbl(AV_RB64(data))); return; case AMF_DATA_TYPE_BOOL: av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); return; case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_LONG_STRING: if (data[-1] == AMF_DATA_TYPE_STRING) { size = bytestream_get_be16(&data); } else { size = bytestream_get_be32(&data); } size = FFMIN(size, sizeof(buf) - 1); memcpy(buf, data, size); buf[size] = 0; av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); return; case AMF_DATA_TYPE_NULL: av_log(ctx, AV_LOG_DEBUG, " NULL\n"); return; case AMF_DATA_TYPE_ARRAY: data += 4; case AMF_DATA_TYPE_OBJECT: av_log(ctx, AV_LOG_DEBUG, " {\n"); for (;;) { int t; size = bytestream_get_be16(&data); av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1)); if (!size) { av_log(ctx, AV_LOG_DEBUG, " }\n"); data++; break; } if (size >= data_end - data) return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); ff_amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; data += t; } return; case AMF_DATA_TYPE_OBJECT_END: av_log(ctx, AV_LOG_DEBUG, " }\n"); return; default: return; } }
static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) { int payload_len; while (len >= 2) { switch (buf[1]) { case RTCP_SR: if (len < 16) { av_log(NULL, AV_LOG_ERROR, "Invalid length for RTCP SR packet\n"); return AVERROR_INVALIDDATA; } payload_len = (AV_RB16(buf + 2) + 1) * 4; s->last_rtcp_ntp_time = AV_RB64(buf + 8); s->last_rtcp_timestamp = AV_RB32(buf + 16); if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) { s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; if (!s->base_timestamp) s->base_timestamp = s->last_rtcp_timestamp; s->rtcp_ts_offset = s->last_rtcp_timestamp - s->base_timestamp; } buf += payload_len; len -= payload_len; break; case RTCP_BYE: return -RTCP_BYE; default: return -1; } } return -1; }
static int xpm_probe(AVProbeData *p) { const uint8_t *b = p->buf; if (AV_RB64(b) == 0x2f2a2058504d202a && *(b+8) == '/') return AVPROBE_SCORE_MAX - 1; return 0; }
static int png_probe(AVProbeData *p) { const uint8_t *b = p->buf; if (AV_RB64(b) == 0x89504e470d0a1a0a) return AVPROBE_SCORE_MAX - 1; return 0; }
static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) { if (buf[1] != 200) return -1; s->last_rtcp_ntp_time = AV_RB64(buf + 8); s->last_rtcp_timestamp = AV_RB32(buf + 16); return 0; }
/* return < 0 if eof */ static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt) { int size; FFMContext *ffm = s->priv_data; int duration, ret; switch(ffm->read_state) { case READ_HEADER: if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0) return ret; av_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n", avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size); if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != FRAME_HEADER_SIZE) return -1; if (ffm->header[1] & FLAG_DTS) if (ffm_read_data(s, ffm->header+16, 4, 1) != 4) return -1; ffm->read_state = READ_DATA; /* fall through */ case READ_DATA: size = AV_RB24(ffm->header + 2); if ((ret = ffm_is_avail_data(s, size)) < 0) return ret; duration = AV_RB24(ffm->header + 5); if (av_new_packet(pkt, size) < 0) { return AVERROR(ENOMEM); } pkt->stream_index = ffm->header[0]; if ((unsigned)pkt->stream_index >= s->nb_streams) { av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index); av_free_packet(pkt); ffm->read_state = READ_HEADER; return -1; } pkt->pos = avio_tell(s->pb); if (ffm->header[1] & FLAG_KEY_FRAME) pkt->flags |= AV_PKT_FLAG_KEY; ffm->read_state = READ_HEADER; if (ffm_read_data(s, pkt->data, size, 0) != size) { /* bad case: desynchronized packet. we cancel all the packet loading */ av_free_packet(pkt); return -1; } pkt->pts = AV_RB64(ffm->header+8); if (ffm->header[1] & FLAG_DTS) pkt->dts = pkt->pts - AV_RB32(ffm->header+16); else pkt->dts = pkt->pts; pkt->duration = duration; break; } return 0; }
static int j2k_probe(AVProbeData *p) { const uint8_t *b = p->buf; if (AV_RB64(b) == 0x0000000c6a502020 || AV_RB32(b) == 0xff4fff51) return AVPROBE_SCORE_EXTENSION + 1; return 0; }
static int dds_probe(AVProbeData *p) { const uint8_t *b = p->buf; if ( AV_RB64(b) == 0x444453207c000000 && AV_RL32(b + 8) && AV_RL32(b + 12)) return AVPROBE_SCORE_MAX - 1; return 0; }
static int redspark_probe(AVProbeData *p) { uint32_t key, data; uint8_t header[8]; /* Decrypt first 8 bytes of the header */ data = AV_RB32(p->buf); key = data ^ 0x52656453; data ^= key; AV_WB32(header, data); key = rol(key, 11); key += rol(key, 3); data = AV_RB32(p->buf + 4) ^ key; AV_WB32(header + 4, data); if (AV_RB64(header) == AV_RB64("RedSpark")) return AVPROBE_SCORE_MAX; return 0; }
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, const uint8_t *name, uint8_t *dst, int dst_size) { int namelen = strlen((char *)name); int len; while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) { len = ff_amf_tag_size(data, data_end); if (len < 0) len = data_end - data; data += len; } if (data_end - data < 3) return -1; data++; for (;;) { int size = bytestream_get_be16(&data); if (!size) break; if (data + size >= data_end || data + size < data) return -1; data += size; if (size == namelen && !memcmp(data-size, name, namelen)) { switch (*data++) { case AMF_DATA_TYPE_NUMBER: snprintf((char *)dst, dst_size, "%g", av_int2dbl(AV_RB64(data))); break; case AMF_DATA_TYPE_BOOL: snprintf((char *)dst, dst_size, "%s", *data ? "true" : "false"); break; case AMF_DATA_TYPE_STRING: len = bytestream_get_be16(&data); av_strlcpy((char *)dst, (const char*)data, FFMIN(len+1, dst_size)); break; default: return -1; } return 0; } len = ff_amf_tag_size(data, data_end); if (len < 0 || data + len >= data_end || data + len < data) return -1; data += len; } return -1; }
int av_packet_split_side_data(AVPacket *pkt){ if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ int i; unsigned int size, orig_pktsize = pkt->size; uint8_t *p; p = pkt->data + pkt->size - 8 - 5; for (i=1; ; i++){ size = AV_RB32(p); if (size>INT_MAX || p - pkt->data < size) return 0; if (p[4]&128) break; p-= size+5; } pkt->side_data = av_malloc(i * sizeof(*pkt->side_data)); if (!pkt->side_data) return AVERROR(ENOMEM); p= pkt->data + pkt->size - 8 - 5; for (i=0; ; i++){ size= AV_RB32(p); av_assert0(size<=INT_MAX && p - pkt->data >= size); pkt->side_data[i].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); pkt->side_data[i].size = size; pkt->side_data[i].type = p[4]&127; if (!pkt->side_data[i].data) return AVERROR(ENOMEM); memcpy(pkt->side_data[i].data, p-size, size); pkt->size -= size + 5; if(p[4]&128) break; p-= size+5; } pkt->size -= 8; /* FFMIN() prevents overflow in case the packet wasn't allocated with * proper padding. * If the side data is smaller than the buffer padding size, the * remaining bytes should have already been filled with zeros by the * original packet allocation anyway. */ memset(pkt->data + pkt->size, 0, FFMIN(orig_pktsize - pkt->size, FF_INPUT_BUFFER_PADDING_SIZE)); pkt->side_data_elems = i+1; return 1; } return 0; }
int av_packet_split_side_data(AVPacket *pkt){ if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ int i; unsigned int size; uint8_t *p; p = pkt->data + pkt->size - 8 - 5; for (i=1; ; i++){ size = AV_RB32(p); if (size>INT_MAX - 5 || p - pkt->data < size) return 0; if (p[4]&128) break; if (p - pkt->data < size + 5) return 0; p-= size+5; } if (i > AV_PKT_DATA_NB) return AVERROR(ERANGE); pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data)); if (!pkt->side_data) return AVERROR(ENOMEM); p= pkt->data + pkt->size - 8 - 5; for (i=0; ; i++){ size= AV_RB32(p); av_assert0(size<=INT_MAX - 5 && p - pkt->data >= size); pkt->side_data[i].data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); pkt->side_data[i].size = size; pkt->side_data[i].type = p[4]&127; if (!pkt->side_data[i].data) return AVERROR(ENOMEM); memcpy(pkt->side_data[i].data, p-size, size); pkt->size -= size + 5; if(p[4]&128) break; p-= size+5; } pkt->size -= 8; pkt->side_data_elems = i+1; return 1; } return 0; }
static int mov_text_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt) { AVSubtitle *sub = data; MovTextContext *m = avctx->priv_data; int ret, ts_start, ts_end; AVBPrint buf; char *ptr = avpkt->data; char *end; int text_length, tsmb_type, ret_tsmb; uint64_t tsmb_size; const uint8_t *tsmb; if (!ptr || avpkt->size < 2) return AVERROR_INVALIDDATA; /* * A packet of size two with value zero is an empty subtitle * used to mark the end of the previous non-empty subtitle. * We can just drop them here as we have duration information * already. If the value is non-zero, then it's technically a * bad packet. */ if (avpkt->size == 2) return AV_RB16(ptr) == 0 ? 0 : AVERROR_INVALIDDATA; /* * The first two bytes of the packet are the length of the text string * In complex cases, there are style descriptors appended to the string * so we can't just assume the packet size is the string size. */ text_length = AV_RB16(ptr); end = ptr + FFMIN(2 + text_length, avpkt->size); ptr += 2; ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); ts_end = av_rescale_q(avpkt->pts + avpkt->duration, avctx->time_base, (AVRational){1,100}); tsmb_size = 0; m->tracksize = 2 + text_length; m->style_entries = 0; m->box_flags = 0; m->count_s = 0; // Note that the spec recommends lines be no longer than 2048 characters. av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (text_length + 2 != avpkt->size) { while (m->tracksize + 8 <= avpkt->size) { // A box is a minimum of 8 bytes. tsmb = ptr + m->tracksize - 2; tsmb_size = AV_RB32(tsmb); tsmb += 4; tsmb_type = AV_RB32(tsmb); tsmb += 4; if (tsmb_size == 1) { if (m->tracksize + 16 > avpkt->size) break; tsmb_size = AV_RB64(tsmb); tsmb += 8; m->size_var = 16; } else m->size_var = 8; //size_var is equal to 8 or 16 depending on the size of box if (m->tracksize + tsmb_size > avpkt->size) break; for (size_t i = 0; i < box_count; i++) { if (tsmb_type == box_types[i].type) { if (m->tracksize + m->size_var + box_types[i].base_size > avpkt->size) break; ret_tsmb = box_types[i].decode(tsmb, m, avpkt); if (ret_tsmb == -1) break; } } m->tracksize = m->tracksize + tsmb_size; } text_to_ass(&buf, ptr, end, m); mov_text_cleanup(m); } else text_to_ass(&buf, ptr, end, m); ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_end - ts_start); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; *got_sub_ptr = sub->num_rects > 0; return avpkt->size; }
static int mov_text_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt) { AVSubtitle *sub = data; int ret, ts_start, ts_end; AVBPrint buf; char *ptr = avpkt->data; char *end; //char *ptr_temp; int text_length, tsmb_type, style_entries; uint64_t tsmb_size, tracksize; StyleBox **s = {0, }; StyleBox *s_temp; const uint8_t *tsmb; int count, i, size_var; if (!ptr || avpkt->size < 2) return AVERROR_INVALIDDATA; /* * A packet of size two with value zero is an empty subtitle * used to mark the end of the previous non-empty subtitle. * We can just drop them here as we have duration information * already. If the value is non-zero, then it's technically a * bad packet. */ if (avpkt->size == 2) return AV_RB16(ptr) == 0 ? 0 : AVERROR_INVALIDDATA; /* * The first two bytes of the packet are the length of the text string * In complex cases, there are style descriptors appended to the string * so we can't just assume the packet size is the string size. */ text_length = AV_RB16(ptr); end = ptr + FFMIN(2 + text_length, avpkt->size); ptr += 2; ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); ts_end = av_rescale_q(avpkt->pts + avpkt->duration, avctx->time_base, (AVRational){1,100}); tsmb_size = 0; tracksize = 2 + text_length; // Note that the spec recommends lines be no longer than 2048 characters. av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (text_length + 2 != avpkt->size) { while (tracksize + 8 <= avpkt->size) { // A box is a minimum of 8 bytes. tsmb = ptr + tracksize - 2; tsmb_size = AV_RB32(tsmb); tsmb += 4; tsmb_type = AV_RB32(tsmb); tsmb += 4; if (tsmb_size == 1) { if (tracksize + 16 > avpkt->size) break; tsmb_size = AV_RB64(tsmb); tsmb += 8; size_var = 18; } else size_var = 10; //size_var is equal to 10 or 18 depending on the size of box if (tracksize + tsmb_size > avpkt->size) break; if (tsmb_type == MKBETAG('s','t','y','l')) { if (tracksize + size_var > avpkt->size) break; style_entries = AV_RB16(tsmb); tsmb += 2; // A single style record is of length 12 bytes. if (tracksize + size_var + style_entries * 12 > avpkt->size) break; count = 0; for(i = 0; i < style_entries; i++) { s_temp = av_malloc(sizeof(*s_temp)); if (!s_temp) goto error; s_temp->style_start = AV_RB16(tsmb); tsmb += 2; s_temp->style_end = AV_RB16(tsmb); tsmb += 2; // fontID = AV_RB16(tsmb); tsmb += 2; s_temp->style_flag = AV_RB8(tsmb); av_dynarray_add(&s, &count, s_temp); if(!s) goto error; //fontsize=AV_RB8(tsmb); tsmb += 2; // text-color-rgba tsmb += 4; } text_to_ass(&buf, ptr, end, s, style_entries); for(i = 0; i < count; i++) { av_freep(&s[i]); } av_freep(&s); } tracksize = tracksize + tsmb_size; } } else text_to_ass(&buf, ptr, end, NULL, 0); ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_end - ts_start); av_bprint_finalize(&buf, NULL); if (ret < 0) return ret; *got_sub_ptr = sub->num_rects > 0; return avpkt->size; error: for(i = 0; i < count; i++) { av_freep(&s[i]); } av_freep(&s); if (s_temp) av_freep(&s_temp); av_bprint_finalize(&buf, NULL); return AVERROR(ENOMEM); }
static void amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) { unsigned int size, nb = -1; char buf[1024]; AMFDataType type; int parse_key = 1; if (data >= data_end) return; switch ((type = *data++)) { case AMF_DATA_TYPE_NUMBER: av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2double(AV_RB64(data))); return; case AMF_DATA_TYPE_BOOL: av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); return; case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_LONG_STRING: if (type == AMF_DATA_TYPE_STRING) { size = bytestream_get_be16(&data); } else { size = bytestream_get_be32(&data); } size = FFMIN(size, sizeof(buf) - 1); memcpy(buf, data, size); buf[size] = 0; av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); return; case AMF_DATA_TYPE_NULL: av_log(ctx, AV_LOG_DEBUG, " NULL\n"); return; case AMF_DATA_TYPE_ARRAY: parse_key = 0; case AMF_DATA_TYPE_MIXEDARRAY: nb = bytestream_get_be32(&data); case AMF_DATA_TYPE_OBJECT: av_log(ctx, AV_LOG_DEBUG, " {\n"); while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) { int t; if (parse_key) { size = bytestream_get_be16(&data); size = FFMIN(size, sizeof(buf) - 1); if (!size) { av_log(ctx, AV_LOG_DEBUG, " }\n"); data++; break; } memcpy(buf, data, size); buf[size] = 0; if (size >= data_end - data) return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); } amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; data += t; } return; case AMF_DATA_TYPE_OBJECT_END: av_log(ctx, AV_LOG_DEBUG, " }\n"); return; default: return; } }