📄 matroskadec.c.svn-base
字号:
* Put one packet in an application-supplied AVPacket struct. * Returns 0 on success or -1 on failure. */static intmatroska_deliver_packet (MatroskaDemuxContext *matroska, AVPacket *pkt){ if (matroska->num_packets > 0) { memcpy(pkt, matroska->packets[0], sizeof(AVPacket)); av_free(matroska->packets[0]); if (matroska->num_packets > 1) { memmove(&matroska->packets[0], &matroska->packets[1], (matroska->num_packets - 1) * sizeof(AVPacket *)); matroska->packets = av_realloc(matroska->packets, (matroska->num_packets - 1) * sizeof(AVPacket *)); } else { av_freep(&matroska->packets); } matroska->num_packets--; return 0; } return -1;}/* * Put a packet into our internal queue. Will be delivered to the * user/application during the next get_packet() call. */static voidmatroska_queue_packet (MatroskaDemuxContext *matroska, AVPacket *pkt){ matroska->packets = av_realloc(matroska->packets, (matroska->num_packets + 1) * sizeof(AVPacket *)); matroska->packets[matroska->num_packets] = pkt; matroska->num_packets++;}/* * Free all packets in our internal queue. */static voidmatroska_clear_queue (MatroskaDemuxContext *matroska){ if (matroska->packets) { int n; for (n = 0; n < matroska->num_packets; n++) { av_free_packet(matroska->packets[n]); av_free(matroska->packets[n]); } av_free(matroska->packets); matroska->packets = NULL; matroska->num_packets = 0; }}/* * Autodetecting... */static intmatroska_probe (AVProbeData *p){ uint64_t total = 0; int len_mask = 0x80, size = 1, n = 1; uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' }; /* ebml header? */ if (AV_RB32(p->buf) != EBML_ID_HEADER) return 0; /* length of header */ total = p->buf[4]; while (size <= 8 && !(total & len_mask)) { size++; len_mask >>= 1; } if (size > 8) return 0; total &= (len_mask - 1); while (n < size) total = (total << 8) | p->buf[4 + n++]; /* does the probe data contain the whole header? */ if (p->buf_size < 4 + size + total) return 0; /* the header must contain the document type 'matroska'. For now, * we don't parse the whole header but simply check for the * availability of that array of characters inside the header. * Not fully fool-proof, but good enough. */ for (n = 4 + size; n <= 4 + size + total - sizeof(probe_data); n++) if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data))) return AVPROBE_SCORE_MAX; return 0;}/* * From here on, it's all XML-style DTD stuff... Needs no comments. */static intmatroska_parse_info (MatroskaDemuxContext *matroska){ int res = 0; uint32_t id; av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\n"); while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up) { matroska->level_up--; break; } switch (id) { /* cluster timecode */ case MATROSKA_ID_TIMECODESCALE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; matroska->time_scale = num; break; } case MATROSKA_ID_DURATION: { double num; if ((res = ebml_read_float(matroska, &id, &num)) < 0) break; matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE; break; } case MATROSKA_ID_TITLE: { char *text; if ((res = ebml_read_utf8(matroska, &id, &text)) < 0) break; strncpy(matroska->ctx->title, text, sizeof(matroska->ctx->title)-1); av_free(text); break; } default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%x in info header\n", id); /* fall-through */ case MATROSKA_ID_WRITINGAPP: case MATROSKA_ID_MUXINGAPP: case MATROSKA_ID_DATEUTC: case MATROSKA_ID_SEGMENTUID: case EBML_ID_VOID: res = ebml_read_skip(matroska); break; } if (matroska->level_up) { matroska->level_up--; break; } } return res;}static intmatroska_decode_buffer(uint8_t** buf, int* buf_size, MatroskaTrack *track){ uint8_t* data = *buf; int isize = *buf_size; uint8_t* pkt_data = NULL; int pkt_size = isize; int result = 0; int olen; switch (track->encoding_algo) { case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: return track->encoding_settings_len; case MATROSKA_TRACK_ENCODING_COMP_LZO: do { olen = pkt_size *= 3; pkt_data = av_realloc(pkt_data, pkt_size+LZO_OUTPUT_PADDING); result = lzo1x_decode(pkt_data, &olen, data, &isize); } while (result==LZO_OUTPUT_FULL && pkt_size<10000000); if (result) goto failed; pkt_size -= olen; break;#ifdef CONFIG_ZLIB case MATROSKA_TRACK_ENCODING_COMP_ZLIB: { z_stream zstream = {0}; if (inflateInit(&zstream) != Z_OK) return -1; zstream.next_in = data; zstream.avail_in = isize; do { pkt_size *= 3; pkt_data = av_realloc(pkt_data, pkt_size); zstream.avail_out = pkt_size - zstream.total_out; zstream.next_out = pkt_data + zstream.total_out; result = inflate(&zstream, Z_NO_FLUSH); } while (result==Z_OK && pkt_size<10000000); pkt_size = zstream.total_out; inflateEnd(&zstream); if (result != Z_STREAM_END) goto failed; break; }#endif#ifdef CONFIG_BZLIB case MATROSKA_TRACK_ENCODING_COMP_BZLIB: { bz_stream bzstream = {0}; if (BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK) return -1; bzstream.next_in = data; bzstream.avail_in = isize; do { pkt_size *= 3; pkt_data = av_realloc(pkt_data, pkt_size); bzstream.avail_out = pkt_size - bzstream.total_out_lo32; bzstream.next_out = pkt_data + bzstream.total_out_lo32; result = BZ2_bzDecompress(&bzstream); } while (result==BZ_OK && pkt_size<10000000); pkt_size = bzstream.total_out_lo32; BZ2_bzDecompressEnd(&bzstream); if (result != BZ_STREAM_END) goto failed; break; }#endif } *buf = pkt_data; *buf_size = pkt_size; return 0; failed: av_free(pkt_data); return -1;}static intmatroska_add_stream (MatroskaDemuxContext *matroska){ int res = 0; uint32_t id; MatroskaTrack *track; /* start with the master */ if ((res = ebml_read_master(matroska, &id)) < 0) return res; av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n"); /* Allocate a generic track. */ track = av_mallocz(MAX_TRACK_SIZE); track->time_scale = 1.0; strcpy(track->language, "eng"); /* try reading the trackentry headers */ while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up > 0) { matroska->level_up--; break; } switch (id) { /* track number (unique stream ID) */ case MATROSKA_ID_TRACKNUMBER: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; track->num = num; break; } /* track UID (unique identifier) */ case MATROSKA_ID_TRACKUID: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; track->uid = num; break; } /* track type (video, audio, combined, subtitle, etc.) */ case MATROSKA_ID_TRACKTYPE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; if (track->type && track->type != num) { av_log(matroska->ctx, AV_LOG_INFO, "More than one tracktype in an entry - skip\n"); break; } track->type = num; switch (track->type) { case MATROSKA_TRACK_TYPE_VIDEO: case MATROSKA_TRACK_TYPE_AUDIO: case MATROSKA_TRACK_TYPE_SUBTITLE: break; case MATROSKA_TRACK_TYPE_COMPLEX: case MATROSKA_TRACK_TYPE_LOGO: case MATROSKA_TRACK_TYPE_CONTROL: default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown or unsupported track type 0x%x\n", track->type); track->type = MATROSKA_TRACK_TYPE_NONE; break; } break; } /* tracktype specific stuff for video */ case MATROSKA_ID_TRACKVIDEO: { MatroskaVideoTrack *videotrack; if (!track->type) track->type = MATROSKA_TRACK_TYPE_VIDEO; if (track->type != MATROSKA_TRACK_TYPE_VIDEO) { av_log(matroska->ctx, AV_LOG_INFO, "video data in non-video track - ignoring\n"); res = AVERROR_INVALIDDATA; break; } else if ((res = ebml_read_master(matroska, &id)) < 0) break; videotrack = (MatroskaVideoTrack *)track; while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up > 0) { matroska->level_up--; break; } switch (id) { /* fixme, this should be one-up, but I get it here */ case MATROSKA_ID_TRACKDEFAULTDURATION: { uint64_t num; if ((res = ebml_read_uint (matroska, &id, &num)) < 0) break; track->default_duration = num; break; } /* video framerate */ case MATROSKA_ID_VIDEOFRAMERATE: { double num; if ((res = ebml_read_float(matroska, &id, &num)) < 0) break; if (!track->default_duration) track->default_duration = 1000000000/num; break; } /* width of the size to display the video at */ case MATROSKA_ID_VIDEODISPLAYWIDTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->display_width = num; break; } /* height of the size to display the video at */ case MATROSKA_ID_VIDEODISPLAYHEIGHT: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->display_height = num; break; } /* width of the video in the file */ case MATROSKA_ID_VIDEOPIXELWIDTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -