📄 mkv_read.c.svn-base
字号:
all_lace_sizes[i] = 0; do { all_lace_sizes[i] += *buffer; (*size)--; } while (*buffer++ == 0xFF); total += all_lace_sizes[i]; } all_lace_sizes[i] = *size - total; break; case 2: /* fixed-size lacing */ for (i=0; i < *laces; i++) all_lace_sizes[i] = *size / *laces; break; case 3: /* EBML lacing */ { int32_t l; uint64_t num = mkv_ebml_read_vlen_uint(buffer, &l); if (num == EBML_UINT_INVALID) { return 0; } buffer += l; *size -= l; total = all_lace_sizes[0] = num; for (i=1; i < *laces-1; i++) { int64_t snum; snum = mkv_ebml_read_vlen_int(buffer, &l); if (snum == EBML_INT_INVALID) { return 0; } buffer += l; *size -= l; all_lace_sizes[i] = all_lace_sizes[i-1] + snum; total += all_lace_sizes[i]; } all_lace_sizes[i] = *size - total; break; } } break; } return 1;}int mkv_handle_block(struct mkv_read_struct *p, uint8_t *block_buffer, uint64_t block_size, int64_t block_bref, int64_t block_fref, uint8_t simpleblock, int track_id, int skip_to_keyframe) { int32_t tracknum; int32_t current_tracknum, video_tracknum, audio_tracknum; int32_t tmp = 0; int16_t time; uint8_t flags; uint64_t old_block_size; int32_t lace_size[16]; uint8_t laces; int64_t timecode; int res; int use_this_block = 1; current_tracknum = p->file.info->tracks[track_id]->tracknum; video_tracknum = p->file.info->tracks[p->file.video_track_id]->tracknum; audio_tracknum = p->file.info->tracks[p->file.audio_track_ids[p->current_audio_track]]->tracknum; tracknum = mkv_ebml_read_vlen_uint(block_buffer, &tmp); block_buffer += tmp; time = block_buffer[0] << 8 | block_buffer[1]; block_buffer += 2; block_size -= tmp + 2; old_block_size = block_size; flags = block_buffer[0]; memset(lace_size, 0, 16*sizeof(int32_t)); res = mkv_read_block_lacing(block_buffer, &block_size, &laces, lace_size); if (res != 1) return res; block_buffer += old_block_size - block_size; timecode = ((p->cluster_timecode + time - p->file.info->first_timecode) * p->file.info->timecode_scale /1000000.0); if (timecode < 0) timecode = 0; res = 1; if ( tracknum == current_tracknum ) { if ( skip_to_keyframe ) { if ( simpleblock ) { if (!(flags&0x80)) { use_this_block = 0; res = 0; } } else if (block_bref != 0 || block_fref != 0) { use_this_block = 0; res = 0; } } } else { use_this_block = 0; res = 0; if ( !skip_to_keyframe && (tracknum == video_tracknum || tracknum == audio_tracknum) ) use_this_block = 1; } if ( use_this_block ) { int i; struct mkv_read_output_struct packet; for (i=0; i < laces; i++) { memset(&packet, 0, sizeof(struct mkv_read_output_struct)); packet.size = lace_size[i]; packet.data = malloc_64(packet.size); if (packet.data == 0) { return -2; } memcpy(packet.data, block_buffer, packet.size); packet.timestamp = (int)timecode; if ( tracknum == video_tracknum ) tmp = in_mkv_read_queue(p->video_queue, &p->video_queue_size, &p->video_queue_rear, MKV_VIDEO_QUEUE_MAX, &packet); else tmp = in_mkv_read_queue(p->audio_queue, &p->audio_queue_size, &p->audio_queue_rear, MKV_AUDIO_QUEUE_MAX, &packet); if ( tmp == 0 ) { return -1; } block_buffer+=packet.size; if ( tracknum == video_tracknum ) timecode+=(1000LL*p->file.audio_resample_scale/p->file.audio_rate); else timecode+=(1000LL*p->file.video_scale/p->file.video_rate); } } return(res);}char *mkv_read_fill_buffer(struct mkv_read_struct *p, int track_id, int skip_to_keyframe) { int32_t il, tmp; uint64_t l; int res; while (1) { while (p->cluster_size > 0) { uint64_t block_duration = 0; int64_t block_bref = 0, block_fref = 0; while (p->blockgroup_size > 0) { switch (mkv_ebml_read_id(p->reader, &il)) { case MATROSKA_ID_BLOCKDURATION: { block_duration = mkv_ebml_read_uint(p->reader, &l); if (block_duration == EBML_UINT_INVALID) { if( p->block_buffer ) { free_64(p->block_buffer); p->block_buffer = 0; } return("mkv_read_fill_buffer: error block duration"); } break; } case MATROSKA_ID_BLOCK: { p->block_size = mkv_ebml_read_length(p->reader, &tmp); if (p->block_size > SIZE_MAX - MKV_INPUT_PADDING) return("mkv_read_fill_buffer: error block size"); if( p->block_buffer ) { free_64(p->block_buffer); p->block_buffer = 0; } p->block_buffer = malloc_64(p->block_size+ MKV_INPUT_PADDING); if ( !p->block_buffer ) return("mkv_read_fill_buffer: can not malloc_64 block_buffer"); if (buffered_reader_read(p->reader, p->block_buffer, p->block_size) != (uint32_t)(p->block_size)) { free_64(p->block_buffer); p->block_buffer = 0; return("mkv_read_fill_buffer: can not read block"); } l = tmp + p->block_size; break; } case MATROSKA_ID_REFERENCEBLOCK: { int64_t num = mkv_ebml_read_int(p->reader, &l); if (num == EBML_INT_INVALID) { if( p->block_buffer ) { free_64(p->block_buffer); p->block_buffer = 0; } return("mkv_read_fill_buffer: can not find block ref"); } if (num <= 0) block_bref = num; else block_fref = num; break; } case EBML_ID_INVALID: if( p->block_buffer ) { free_64(p->block_buffer); p->block_buffer = 0; } return("mkv_read_fill_buffer: read id invalid"); default: mkv_ebml_read_skip(p->reader, &l); break; } p->blockgroup_size -= l + il; p->cluster_size -= l + il; } if (p->block_buffer) { res = mkv_handle_block(p, (uint8_t *)(p->block_buffer), p->block_size, block_bref, block_fref, 0, track_id, skip_to_keyframe); free_64(p->block_buffer); p->block_buffer = 0; if (res < 0) { if ( res == -1 ) return("mkv_read_fill_buffer: queue is full"); else return("mkv_read_fill_buffer: can not malloc_64 data buffer"); } if (res) return(0); } if (p->cluster_size > 0) { switch (mkv_ebml_read_id(p->reader, &il)) { case MATROSKA_ID_CLUSTERTIMECODE: { uint64_t num = mkv_ebml_read_uint(p->reader, &l); if (num == EBML_UINT_INVALID) return("mkv_read_fill_buffer: invalid cluster timecode"); p->cluster_timecode = num; break; } case MATROSKA_ID_BLOCKGROUP: { p->blockgroup_size = mkv_ebml_read_length(p->reader, &tmp); l = tmp; break; } case MATROSKA_ID_SIMPLEBLOCK: { int res; p->block_size = mkv_ebml_read_length(p->reader, &tmp); if (p->block_size > SIZE_MAX - MKV_INPUT_PADDING) return("mkv_read_fill_buffer: error block size"); if( p->block_buffer ) { free_64(p->block_buffer); p->block_buffer = 0; } p->block_buffer = malloc_64(p->block_size+ MKV_INPUT_PADDING); if ( !p->block_buffer ) return("mkv_read_fill_buffer: can not malloc_64 block_buffer"); if (buffered_reader_read(p->reader, p->block_buffer, p->block_size) != (uint32_t)(p->block_size)) { free_64(p->block_buffer); p->block_buffer = 0; return("mkv_read_fill_buffer: can not read block"); } l = tmp + p->block_size; res = mkv_handle_block (p, (uint8_t *)(p->block_buffer), p->block_size, block_bref, block_fref, 1, track_id, skip_to_keyframe); free_64(p->block_buffer); p->block_buffer = 0; p->cluster_size -= l + il; if (res < 0) { if ( res == -1 ) return("mkv_read_fill_buffer: queue is full"); else return("mkv_read_fill_buffer: can not malloc_64 data buffer"); } else if (res) return(0); else p->cluster_size += l + il; break; } case EBML_ID_INVALID: return("mkv_read_fill_buffer: can not find block");; default: mkv_ebml_read_skip(p->reader, &l); break; } p->cluster_size -= l + il; } } if (mkv_ebml_read_id(p->reader, &il) != MATROSKA_ID_CLUSTER) return("mkv_read_fill_buffer: eof"); p->cluster_size = mkv_ebml_read_length(p->reader, 0); } return(0);}char *mkv_read_seek(struct mkv_read_struct *p, int timestamp) { int32_t video_tracknum = p->file.info->tracks[p->file.video_track_id]->tracknum; int32_t i; mkvinfo_index_t* index = 0; if (timestamp < 0) timestamp = 0; for(i=0; i < p->file.info->total_indexes-1; i++) { if ( p->file.info->indexes[i].tracknum == video_tracknum ) { int64_t timecode = ((p->file.info->indexes[i].timecode - p->file.info->first_timecode) * p->file.info->timecode_scale /1000000.0); int64_t next_timecode = ((p->file.info->indexes[i+1].timecode - p->file.info->first_timecode) * p->file.info->timecode_scale /1000000.0); if (timestamp >= (int)timecode && timestamp < (int)next_timecode) { index = p->file.info->indexes+i; break; } } } if ( index == 0 ) { index = p->file.info->indexes + (p->file.info->total_indexes-1); } buffered_reader_seek(p->reader, index->filepos); p->cluster_size = p->blockgroup_size = 0; clear_mkv_read_queue(p->audio_queue, &p->audio_queue_size, &p->audio_queue_front, &p->audio_queue_rear, MKV_VIDEO_QUEUE_MAX); clear_mkv_read_queue(p->video_queue, &p->video_queue_size, &p->video_queue_front, &p->video_queue_rear, MKV_AUDIO_QUEUE_MAX); return(mkv_read_fill_buffer(p, p->file.video_track_id, 1));}char *mkv_read_get_video(struct mkv_read_struct *p, struct mkv_read_output_struct *output) { if ( p->video_queue_size > 0 ) out_mkv_read_queue(p->video_queue, &p->video_queue_size, &p->video_queue_front, MKV_VIDEO_QUEUE_MAX, output); else { char* res = mkv_read_fill_buffer(p, p->file.video_track_id, 0); if (res) return res; if ( !(p->video_queue_size>0) ) return "mkv_read_get_video: video queue is empty"; out_mkv_read_queue(p->video_queue, &p->video_queue_size, &p->video_queue_front, MKV_VIDEO_QUEUE_MAX, output); } return(0);}char *mkv_read_get_audio(struct mkv_read_struct *p, unsigned int audio_stream, struct mkv_read_output_struct *output){ p->current_audio_track = audio_stream; if ( p->audio_queue_size > 0 ) out_mkv_read_queue(p->audio_queue, &p->audio_queue_size, &p->audio_queue_front, MKV_AUDIO_QUEUE_MAX, output); else { char* res = mkv_read_fill_buffer(p, p->file.audio_track_ids[audio_stream], 0); if (res) return res; if ( !(p->audio_queue_size>0) ) return "mkv_read_get_audio: audio queue is empty"; out_mkv_read_queue(p->audio_queue, &p->audio_queue_size, &p->audio_queue_front, MKV_AUDIO_QUEUE_MAX, output); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -