📄 mpeg2edit.c
字号:
return r;
}
static void delete_block(BLOCK *block)
{
if(block){
if(block->data){
free(block->data);
block->data = 0;
}
block->length = 0;
free(block);
}
}
static int find_block(BLOCK *current, BLOCK *next, int offset, BLOCK *pattern)
{
int r;
int i;
r = offset;
while(r < current->length){
for(i=0;i<pattern->length;i++){
if(r+i<current->length){
if(current->data[r+i] == pattern->data[i]){
continue;
}else{
break;
}
}else if(next != NULL){
if(next->data[r-current->length+i] == pattern->data[i]){
continue;
}else{
break;
}
}else{
return -1;
}
}
if(i == pattern->length){
return r;
}
r += 1;
}
return -1;
}
static unsigned char get_byte_block(BLOCK *current, BLOCK *next, int offset)
{
if(current == NULL){
return 0;
}
if(offset < current->length){
return current->data[offset];
}else if( (next != NULL) && (offset-current->length < next->length) ){
return next->data[offset-current->length];
}
return 0;
}
static void set_byte_block(BLOCK *current, BLOCK *next, int offset, unsigned char data)
{
if(current == NULL){
return;
}
if(offset < current->length){
current->data[offset] = data;
}else if( (next != NULL) && (offset-current->length < next->length) ){
next->data[offset-current->length] = data;
}
}
/*-----------------------------------------------------------------*/
static int subtract_temporal_reference(int current, int previous)
{
if( (previous & 0x0200) && ((current & 0x03fe) == 0) ){
current |= 0x0400;
}
return current - previous;
}
/*-----------------------------------------------------------------*/
static int check_ts(BITSTREAM *in)
{
int i,n;
int o,p,d;
int count[376];
int max, total;
unsigned char buffer[460224];
n = bs_read(in, buffer, sizeof(buffer));
bs_seek(in, SEEK_SET, 0);
o = 0;
for(i=0;i<n;i++){
if(buffer[i] == 0x47){
o = i;
break;
}
}
if(o > 188){
return 0;
}
p = o;
total = 0;
memset(count, 0, sizeof(count));
for(;i<n;i++){
if(buffer[i] == 0x47){
d = i-p;
if(d >= sizeof(count)/sizeof(int)){
return 0;
}
count[d] += 1;
total += 1;
p = i;
}
}
max = 0;
for(i=0;i<sizeof(count)/sizeof(int);i++){
if(max < count[i]){
max = count[i];
}
}
if(max > total/2){
return 1;
}
return 0;
}
/*-----------------------------------------------------------------*/
static int es_open(const char *path, MPEG2EDIT *mpeg2edit)
{
BITSTREAM *bs;
bs = bs_open(path);
if(bs == NULL){
return 0;
}
bs_seek(bs, 0, SEEK_SET);
mpeg2edit->stream = bs;
mpeg2edit->edit = es_edit;
mpeg2edit->close = es_close;
return 1;
}
static void es_edit(void *mpeg2edit, char *out_path, __int64 in, __int64 out)
{
int current_temporal_reference;
int previous_temporal_reference;
int current_percent;
__int64 input_field_count;
__int64 output_field_count;
int closed_gop;
int broken_link;
int fps;
__int64 n;
ES_SEQUENCE_HEADER seq;
ES_GOP_HEADER gop;
ES_FRAME frm;
BITSTREAM *bs;
FILE *file;
bs = (BITSTREAM *)((MPEG2EDIT *)mpeg2edit)->stream;
bs_seek(bs, 0, SEEK_SET);
current_temporal_reference = 0;
previous_temporal_reference = 0;
input_field_count = 0;
memset(&seq, 0, sizeof(seq));
memset(&gop, 0, sizeof(gop));
memset(&frm, 0, sizeof(frm));
closed_gop = 0;
broken_link = 0;
/* 1st step - search stream head I picture */
while(bs_next_packet_prefix(bs)){
switch(bs_read_bits(bs, 32)){
case 0x000001b3:
es_clear_sequence_header(&seq);
es_read_sequence_header(bs, &seq);
break;
case 0x000001b8:
es_clear_gop_header(&gop);
es_read_gop_header(bs, &gop);
current_temporal_reference = 0;
previous_temporal_reference = 0;
closed_gop = es_get_closed_gop(&gop);
break;
case 0x00000100:
es_clear_frame(&frm);
es_read_frame(bs, &frm);
if(es_get_coding_type(&frm) == 1){
if(closed_gop == 0){
broken_link = 1;
}
if(seq.length){
goto ES_EDIT_2ND_STEP;
}
}
break;
default:
bs_erase_bits(bs, 32);
}
}
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
return;
ES_EDIT_2ND_STEP: /* search in point */
if( in == 0 ){
goto ES_EDIT_3RD_STEP;
}
previous_temporal_reference = es_get_temporal_reference(&frm);
if( closed_gop && (in <= subtract_temporal_reference(previous_temporal_reference, 0)) ){
goto ES_EDIT_3RD_STEP;
}
input_field_count += es_get_field_count(&frm);
while(bs_next_packet_prefix(bs)){
current_percent = (int)(input_field_count * 50 / out);
if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, current_percent) != VF_OK){
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
return;
}
switch(bs_read_bits(bs, 32)){
case 0x000001b3:
es_clear_sequence_header(&seq);
es_read_sequence_header(bs, &seq);
break;
case 0x000001b8:
es_clear_gop_header(&gop);
es_read_gop_header(bs, &gop);
closed_gop = es_get_closed_gop(&gop);
broken_link = es_get_broken_link(&gop);
current_temporal_reference = 0;
previous_temporal_reference = 0;
break;
case 0x00000100:
es_clear_frame(&frm);
es_read_frame(bs, &frm);
switch(es_get_coding_type(&frm)){
case 1:
if(broken_link == 1){
broken_link = 2;
current_temporal_reference = 0;
}else{
broken_link = 0;
current_temporal_reference = es_get_temporal_reference(&frm);
}
if(closed_gop == 1){
closed_gop = 2;
}else{
closed_gop = 0;
}
n = (input_field_count+1)/2;
n += subtract_temporal_reference(current_temporal_reference, previous_temporal_reference);
if( n >= in ){
goto ES_EDIT_3RD_STEP;
}
previous_temporal_reference = es_get_temporal_reference(&frm);
input_field_count += es_get_field_count(&frm);
break;
case 2:
broken_link = 0;
closed_gop = 0;
previous_temporal_reference = es_get_temporal_reference(&frm);
input_field_count += es_get_field_count(&frm);
break;
case 3:
if(broken_link == 0){
input_field_count += es_get_field_count(&frm);
}
}
break;
default:
bs_erase_bits(bs, 32);
}
}
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
return;
ES_EDIT_3RD_STEP: /* output data to file */
output_field_count = 0;
fps = es_get_fps(&seq);
es_set_timecode(&gop, 0, fps);
es_set_broken_link(&gop, 0);
file = fopen(out_path, "wb");
if(file == NULL){
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
return;
}
es_write_sequence_header(&seq, file);
es_write_gop_header(&gop, file);
if(closed_gop){
current_temporal_reference = es_get_temporal_reference(&frm);
n = (input_field_count + 1) / 2;
n += subtract_temporal_reference(current_temporal_reference, previous_temporal_reference);
current_temporal_reference -= (n-in);
es_set_temporal_reference(&frm, current_temporal_reference);
previous_temporal_reference = current_temporal_reference;
}else{
previous_temporal_reference = es_get_temporal_reference(&frm);
es_set_temporal_reference(&frm, 0);
}
n = es_get_field_count(&frm);
input_field_count += n;
output_field_count += n;
es_write_frame(&frm, file);
while(bs_next_packet_prefix(bs)){
current_percent = (int)(input_field_count * 50 / out);
if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, current_percent) != VF_OK){
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
return;
}
switch(bs_read_bits(bs, 32)){
case 0x000001b3:
if( (input_field_count+1)/2 >= out ){
goto ES_EDIT_4TH_STEP;
}
es_clear_sequence_header(&seq);
es_read_sequence_header(bs, &seq);
es_write_sequence_header(&seq, file);
break;
case 0x000001b8:
if( (input_field_count+1)/2 >= out ){
goto ES_EDIT_4TH_STEP;
}
es_clear_gop_header(&gop);
es_read_gop_header(bs, &gop);
closed_gop = es_get_closed_gop(&gop);
broken_link = es_get_broken_link(&gop);
current_temporal_reference = 0;
previous_temporal_reference = 0;
es_set_broken_link(&gop, 0);
es_set_timecode(&gop, (output_field_count+1)/2, fps);
es_write_gop_header(&gop, file);
break;
case 0x00000100:
es_clear_frame(&frm);
es_read_frame(bs, &frm);
switch(es_get_coding_type(&frm)){
case 1:
if( (input_field_count+1)/2 >= out ){
goto ES_EDIT_4TH_STEP;
}
if(broken_link == 1){
broken_link = 2;
previous_temporal_reference = es_get_temporal_reference(&frm);
}else{
broken_link = 0;
}
current_temporal_reference = es_get_temporal_reference(&frm);
current_temporal_reference -= previous_temporal_reference;
es_set_temporal_reference(&frm, current_temporal_reference);
es_write_frame(&frm, file);
n = es_get_field_count(&frm);
input_field_count += n;
output_field_count += n;
break;
case 2:
if( (input_field_count+1)/2 >= out ){
goto ES_EDIT_4TH_STEP;
}
broken_link = 0;
current_temporal_reference = es_get_temporal_reference(&frm);
current_temporal_reference -= previous_temporal_reference;
es_set_temporal_reference(&frm, current_temporal_reference);
es_write_frame(&frm, file);
n = es_get_field_count(&frm);
input_field_count += n;
output_field_count += n;
break;
case 3:
n = es_get_field_count(&frm);
if(broken_link == 0){
input_field_count += n;
}
current_temporal_reference = es_get_temporal_reference(&frm);
if(current_temporal_reference < previous_temporal_reference){
es_padding_frame(&frm);
}else{
current_temporal_reference -= previous_temporal_reference;
es_set_temporal_reference(&frm, current_temporal_reference);
output_field_count += n;
}
es_write_frame(&frm, file);
}
break;
default:
bs_erase_bits(bs, 32);
}
}
ES_EDIT_4TH_STEP:
es_write_sequence_end_code(file);
es_clear_sequence_header(&seq);
es_clear_gop_header(&gop);
es_clear_frame(&frm);
fclose(file);
((MPEG2EDIT *)mpeg2edit)->callback(out_path, 100);
return;
}
static void es_close(void *mpeg2edit)
{
MPEG2EDIT *p;
BITSTREAM *bs;
p = (MPEG2EDIT *)mpeg2edit;
bs = (BITSTREAM *)p->stream;
bs_close(bs);
p->stream = NULL;
p->edit = dummy_edit;
p->close = dummy_close;
}
static int es_read_sequence_header(BITSTREAM *in, ES_SEQUENCE_HEADER *out)
{
if(bs_read_bits(in, 32) != 0x000001b3){
return 0;
}
out->head = read_list(in, 512, es_judge_read_sequence_header_end);
out->length = count_list_size(out->head);
return out->length;
}
static int es_read_gop_header(BITSTREAM *in, ES_GOP_HEADER *out)
{
if(bs_read_bits(in, 32) != 0x000001b8){
return 0;
}
out->head = read_list(in, 128, es_judge_read_gop_header_end);
out->length = count_list_size(out->head);
return out->length;
}
static int es_read_picture(BITSTREAM *in, ES_PICTURE *out)
{
if(bs_read_bits(in, 32) != 0x00000100){
return 0;
}
out->head = read_list(in, 8192, es_judge_read_picture_end);
out->length = count_list_size(out->head);
return out->length;
}
static int es_read_frame(BITSTREAM *in, ES_FRAME *out)
{
int r;
r = es_read_picture(in, &(out->fst));
if(es_get_picture_field_count(&(out->fst)) == 1){
r += es_read_picture(in, &(out->snd));
}
return r;
}
static int es_judge_read_sequence_header_end(int code)
{
if(code == 0x00000100){ /* picture_start_code */
return 1;
}else if(code == 0x000001b8){ /* gop_start_code */
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -