⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg3vtrack.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
字号:
#include "libmpeg3.h"#include "mpeg3private.h"#include "mpeg3protos.h"#include "mpeg3vtrack.h"#include "video/mpeg3video.h"#include "video/mpeg3videoprotos.h"#include "mp4av.h"#include <stdlib.h>void mpeg3vtrack_cleanup_frame (mpeg3_vtrack_t *track){  long size;  if (track->track_frame_buffer == NULL) return;  size = track->track_frame_buffer_size;  track->track_frame_buffer[0] = track->track_frame_buffer[size - 4];  track->track_frame_buffer[1] = track->track_frame_buffer[size - 3];  track->track_frame_buffer[2] = track->track_frame_buffer[size - 2];  track->track_frame_buffer[3] = track->track_frame_buffer[size - 1];#if 0  printf("Clean up - code is %x %x %x %x\n",	 track->track_frame_buffer[0],	 track->track_frame_buffer[1],	 track->track_frame_buffer[2],	 track->track_frame_buffer[3]);#endif  track->track_frame_buffer_size = 4;}static int mpeg3vtrack_locate_frame (mpeg3_vtrack_t *track,			    long frame){  mpeg3_demuxer_t *demux;  long start_frame;  uint32_t offset;  uint32_t code = 0;  demux = track->demuxer;  if (frame < track->current_position) {    mpeg3demux_seek_start(demux);    start_frame = 0;  } else    start_frame = track->current_position;  // clean out last frame  while (!mpeg3demux_eof(demux)) {    mpeg3vtrack_cleanup_frame(track);    offset = 4;    track->track_frame_buffer_size =     mpeg3demux_read_data(demux,			 track->track_frame_buffer,			 track->track_frame_buffer_maxsize);    for (offset = 4, code = 0; offset < track->track_frame_buffer_size - 3; offset++) {      code <<= 8;      code |= track->track_frame_buffer[offset];      if (code == MPEG3_PICTURE_START_CODE) {	start_frame++;	if (start_frame >= frame) {	  for (offset = offset - 3; 	       offset < track->track_frame_buffer_size; 	       offset++) {	    mpeg3demux_read_prev_char(demux);	  }	  track->track_frame_buffer_size = 0;	  track->current_position = frame;	  return 0;	}      }    }  }  return 1;}        staticint mpeg3vtrack_get_frame (mpeg3_vtrack_t *track){	uint32_t code = 0;	int have_pict_start, done;	mpeg3_demuxer_t *demux = track->demuxer;	unsigned char *output;	have_pict_start = 0;	track->current_position++;	output = track->track_frame_buffer;	if ((track->track_frame_buffer_size != 0) &&	    output[0] == 0 && output[1] == 0 && output[2] == 1) {	  if (output[3] == 0)	      have_pict_start = 1;	    output += 4;	} 	done = 0;	while(done == 0 && 		code != MPEG3_SEQUENCE_END_CODE &&		!mpeg3demux_eof(demux))	{	  if (track->track_frame_buffer_size + 3 >= 	      track->track_frame_buffer_maxsize) {	    int diff = output - track->track_frame_buffer;	    track->track_frame_buffer_maxsize += 4096;	    track->track_frame_buffer = 	      realloc(track->track_frame_buffer, 		      track->track_frame_buffer_maxsize);	    if (track->track_frame_buffer == NULL) exit(1);	    output = track->track_frame_buffer + diff;	  }	  	  code <<= 8;	  // can't do this yet - we're still reading from the demuxer...	  *output = mpeg3demux_read_char(track->demuxer);	  code |= *output++;	  //	  printf("%d %08x\n", track->track_frame_buffer_size, code);	  track->track_frame_buffer_size++;	  if (code == MPEG3_PICTURE_START_CODE) {	    if (have_pict_start == 1) done = 1;	    have_pict_start = 1;	  } else if ((code == MPEG3_GOP_START_CODE) ||		     (code == MPEG3_SEQUENCE_START_CODE)) {	    if (have_pict_start == 1) done = 1;	  }	}	return mpeg3demux_eof(demux);}/* Line up on the beginning of the previous code. */int mpeg3vtrack_prev_code(mpeg3_demuxer_t* demux, uint32_t code){  uint32_t testcode = 0;  int bytes = 0;  if (mpeg3demux_bof(demux)) return mpeg3demux_bof(demux);  do {    testcode >>= 8;    testcode |= (mpeg3demux_read_prev_char(demux) << 24);    bytes++;  } while(!mpeg3demux_bof(demux) && testcode != code);  return mpeg3demux_bof(demux);}// Must perform seeking now to get timecode for audioint mpeg3vtrack_seek_percentage(mpeg3_vtrack_t *vtrack, double percentage){  vtrack->percentage_seek = percentage;  return 0;}int mpeg3vtrack_seek_frame(mpeg3_vtrack_t *vtrack, long frame){  vtrack->frame_seek = frame;  return 0;}int mpeg3vtrack_seek(mpeg3_vtrack_t *track, int dont_decode){  long this_gop_start;  int result = 0;  int back_step;  int attempts;  mpeg3_t *file = track->file;  int is_video_stream = file->is_video_stream;  double percentage;  long frame_number;  int match_refframes = 1;  mpeg3_demuxer_t *demux = track->demuxer;  int ix;  // Must do seeking here so files which don't use video don't seek.  /* Seek to percentage */  if(track->percentage_seek >= 0)    {      //printf("mpeg3video_seek 1 %f\n", video->percentage_seek);      track->track_frame_buffer_size = 0;      percentage = track->percentage_seek;      track->percentage_seek = -1;      mpeg3demux_seek_percentage(track->demuxer, percentage);      printf("Seek time is %g\n", mpeg3demux_get_time(track->demuxer));    }  else    /* Seek to a frame */    if(track->frame_seek >= 0)      {	frame_number = track->frame_seek;	track->frame_seek = -1;	if(frame_number < 0) frame_number = 0;	if(frame_number > track->total_frames) 	  frame_number = track->total_frames;	//printf("mpeg3video_seek 1 %ld %ld\n", frame_number, video->framenum);	/* Seek to I frame in table of contents */	if(track->frame_offsets)	  {	    int i;	    for(i = track->total_keyframe_numbers - 1; i >= 0; i--)	      {		if(track->keyframe_numbers[i] <= frame_number)		  {		    int frame;		    int title_number;		    int64_t byte;		    // Go 2 I-frames before current position		    frame = track->keyframe_numbers[i];		    title_number = (track->frame_offsets[frame] & 				    0xff00000000000000) >> 56;		    byte = track->frame_offsets[frame] & 		      0xffffffffffffff;		    mpeg3demux_open_title(demux, title_number);		    mpeg3demux_seek_byte(demux, byte);		    for (ix = frame; ix < frame_number; ix++) {		      mpeg3vtrack_get_frame(track);		    }		    break;		  }	      }	  }	else	  /* Seek to start of file */	  {	  if(frame_number < 16)	    {	      mpeg3demux_seek_start(demux);	      for (ix = 0; ix < frame_number; ix++) {		mpeg3vtrack_get_frame(track);	      }#if 0	      track->video->repeat_count = track->video->current_repeat = 0;	      track->video->framenum = 0;	      result = mpeg3vtrack_drop_frames(track, 					       frame_number - video->framenum);#endif	    }	  else	    {	      /* Seek to an I frame. */		  /* Elementary stream */		  if(is_video_stream)		    {#if 0		      //mpeg3_t *file = video->file;		      mpeg3_vtrack_t *track = video->track;		      int64_t byte = (int64_t)((double)(mpeg3demuxer_total_bytes(vstream->demuxer) / 							track->total_frames) * 					       frame_number);		      long minimum = 65535;		      int done = 0;		      //printf("seek elementary %d\n", frame_number);		      /* Get GOP just before frame */		      do			{			  result = mpeg3demux_seek_byte(demux, byte);			  if(!result) 			    result = mpeg3vtrack_prev_code(demux, MPEG3_GOP_START_CODE);			  mpeg3demux_read_char(demux);			  if(!result) result = mpeg3video_getgophdr(video);			  this_gop_start = mpeg3video_goptimecode_to_frame(video);			  //printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result);			  if(labs(this_gop_start - frame_number) >= labs(minimum)) 			    done = 1;			  else			    {			      minimum = this_gop_start - frame_number;			      byte += (long)((float)(frame_number - this_gop_start) * 					     (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / 						     track->total_frames));			      if(byte < 0) byte = 0;			    }			}while(!result && !done);		      //printf("wanted %d guessed %d\n", frame_number, this_gop_start);		      if(!result)			{			  video->framenum = this_gop_start;			  result = mpeg3video_drop_frames(video, frame_number - video->framenum);			}#endif		    }		  else		    /* System stream */		    {		      mpeg3vtrack_locate_frame(track, frame_number);#if 0		      mpeg3demux_seek_time(demux, ((double)frame_number) / track->frame_rate);		      percentage = mpeg3demux_tell_percentage(demux);#endif		      //printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream));		    }		}	    }      }  return result;}int mpeg3vtrack_previous_frame(mpeg3_vtrack_t *vtrack){  int ix;  if(mpeg3demux_tell_percentage(vtrack->demuxer) <= 0) return 1;  // Get one picture  mpeg3vtrack_prev_code(vtrack->demuxer, MPEG3_PICTURE_START_CODE);  for (ix = 0; ix < 4; ix++) {    mpeg3demux_read_prev_char(vtrack->demuxer);  }  if(mpeg3demux_bof(vtrack->demuxer))     mpeg3demux_seek_percentage(vtrack->demuxer, 0);  //  vtrack->video->repeat_count = 0;  return 0;}#if 0int mpeg3vtrack_drop_frames(mpeg3_vtrack_t *vtrack, long frames){  int result = 0;  long frame_number = video->framenum + frames;  /* Read the selected number of frames and skip b-frames */  while(!result && frame_number > video->framenum)    {      result = mpeg3video_read_frame_backend(video, frame_number - video->framenum);    }  return result;}#endif/* ======================================================================= *//*                                    ENTRY POINTS *//* ======================================================================= */mpeg3_vtrack_t* mpeg3_new_vtrack(mpeg3_t *file, 	int stream_id, 	mpeg3_demuxer_t *demuxer,	int number){  uint32_t h,w;  int have_mpeg2;  double frame_rate, bitrate;	int result = 0;	mpeg3_vtrack_t *new_vtrack;	new_vtrack = calloc(1, sizeof(mpeg3_vtrack_t));	new_vtrack->file = file;	new_vtrack->demuxer = mpeg3_new_demuxer(file, 0, 1, stream_id);	if(new_vtrack->demuxer) mpeg3demux_copy_titles(new_vtrack->demuxer, demuxer);	new_vtrack->current_position = 0;	new_vtrack->percentage_seek = -1;	new_vtrack->frame_seek = -1;	new_vtrack->track_frame_buffer = NULL;	new_vtrack->track_frame_buffer_maxsize = 0;//printf("mpeg3_new_vtrack 1\n");// Copy pointers	if(file->frame_offsets)	{		new_vtrack->frame_offsets = file->frame_offsets[number];		new_vtrack->total_frame_offsets = file->total_frame_offsets[number];		new_vtrack->keyframe_numbers = file->keyframe_numbers[number];		new_vtrack->total_keyframe_numbers = file->total_keyframe_numbers[number];	}//printf("mpeg3_new_vtrack 1\n");//printf("mpeg3_new_vtrack %llx\n", mpeg3demux_tell(new_vtrack->demuxer));/* Get information about the track here. */	if (mpeg3vtrack_get_frame(new_vtrack)) {	  mpeg3_delete_vtrack(file, new_vtrack);	  return NULL;	}		if (MP4AV_Mpeg3ParseSeqHdr(new_vtrack->track_frame_buffer, 				   new_vtrack->track_frame_buffer_size, 				   &have_mpeg2,				   &h,				   &w, 				   &frame_rate,				   &bitrate) < 0) {	  mpeg3_delete_vtrack(file, new_vtrack);	  return NULL;	}	new_vtrack->frame_rate = frame_rate;	new_vtrack->width = w;	new_vtrack->height = h;	new_vtrack->mpeg_layer = have_mpeg2 ? 2 : 1;	mpeg3demux_seek_start(new_vtrack->demuxer);	new_vtrack->track_frame_buffer_size = 0;	if (!new_vtrack->frame_offsets) {	  if (file->is_video_stream) {	  } else {	    new_vtrack->total_frames = 	      (long)(mpeg3demux_length(new_vtrack->demuxer) * frame_rate);	  }	} else {	  new_vtrack->total_frames = new_vtrack->total_frame_offsets;	}//printf("mpeg3_new_vtrack 2\n");	return new_vtrack;}int mpeg3_delete_vtrack(mpeg3_t *file, mpeg3_vtrack_t *vtrack){	if(vtrack->demuxer) mpeg3_delete_demuxer(vtrack->demuxer);	if(vtrack->track_frame_buffer) free(vtrack->track_frame_buffer);	free(vtrack);	return 0;}/* Read all the way up to and including the next picture start code */int mpeg3vtrack_read_raw (mpeg3_vtrack_t *vtrack, 			  unsigned char *output, 			  long *size, 			  long max_size){  uint32_t code = 0;  mpeg3_demuxer_t *demux = vtrack->demuxer;  *size = 0;  while(code != MPEG3_PICTURE_START_CODE && 	code != MPEG3_SEQUENCE_END_CODE &&	*size < max_size && 	!mpeg3demux_eof(demux))    {      code <<= 8;      *output = mpeg3demux_read_char(demux);      code |= *output++;      (*size)++;    }  return mpeg3demux_eof(demux);}/* Read all the way up to and including the next picture start code */int mpeg3vtrack_read_raw_resize (mpeg3_vtrack_t *vtrack, 				 unsigned char **optr, 				 long *size, 				 int first){  int result = 0;  result = mpeg3vtrack_seek(vtrack, 1);    if (!result) result = mpeg3vtrack_get_frame(vtrack);  if (!result) {    *optr = vtrack->track_frame_buffer;    *size = vtrack->track_frame_buffer_size;  }  return result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -