📄 video.c
字号:
shmemFlag = 0; if (!quietFlag) { fprintf(stderr, "Shared memory error, disabling.\n"); fprintf(stderr, "Ximage error.\n"); } goto shmemerror; } /* Success here, continue. */#ifdef LITTLE_ENDIAN_ARCHITECTURE new->ximage->byte_order = LSBFirst; new->ximage->bitmap_bit_order = LSBFirst;#else new->ximage->byte_order = MSBFirst; new->ximage->bitmap_bit_order = MSBFirst;#endif new->shminfo.shmid = shmget(IPC_PRIVATE, (unsigned int) (new->ximage->bytes_per_line * new->ximage->height), IPC_CREAT | 0777); if (new->shminfo.shmid < 0) { XDestroyImage(new->ximage); new->ximage = NULL; shmemFlag = 0; if (!quietFlag) { fprintf(stderr, "Shared memory error, disabling.\n"); fprintf(stderr, "Seg. id. error.\n"); } goto shmemerror; } new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0); if (new->shminfo.shmaddr == ((char *) -1)) { XDestroyImage(new->ximage); new->ximage = NULL; shmemFlag = 0; if (!quietFlag) { fprintf(stderr, "Shared memory error, disabling.\n"); fprintf(stderr, "Address error.\n"); } goto shmemerror; } new->ximage->data = new->shminfo.shmaddr; new->display = (unsigned char *) new->ximage->data; new->shminfo.readOnly = False; XShmAttach(display, &(new->shminfo)); XSync(display, False); if (gXErrorFlag) { /* Ultimate failure here. */ XShmDetach(display,&(new->shminfo)); XSync(display, False); XDestroyImage(new->ximage); shmdt (new->shminfo.shmaddr); shmctl (new->shminfo.shmid, IPC_RMID, 0); new->ximage = NULL; shmemFlag = 0; if (!quietFlag) { fprintf(stderr, "Shared memory error, disabling.\n"); } gXErrorFlag = 0; goto shmemerror; } else { shmctl(new->shminfo.shmid, IPC_RMID, 0); } if (!quietFlag) { fprintf(stderr, "Sharing memory.\n"); } } else#endif { int temp_sz; int factor;shmemerror:#ifndef DISABLE_DITHER temp_sz = vid_stream->matched_depth >> 3;#else temp_sz = 4;#endif if(!temp_sz) temp_sz = 1; if(temp_sz == 3) temp_sz = 4; factor = 1 + IS_2x2_DITHER(ditherType); /* 1 or 2 */ new->display = (unsigned char *) malloc(width * height * temp_sz * factor * factor); } new->luminance = (unsigned char *) malloc(width * height); new->Cr = (unsigned char *) malloc(width * height / 4); new->Cb = (unsigned char *) malloc(width * height / 4); /* Reset locked flag. */ new->locked = 0; /* Return pointer to new structure. */ return new;}/* *-------------------------------------------------------------- * * DestroyPictImage -- * * Deallocates a PictImage structure. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */voidDestroyPictImage(apictimage, xinfo) PictImage *apictimage; XInfo *xinfo;{ if (apictimage->luminance != NULL) { free(apictimage->luminance); } if (apictimage->Cr != NULL) { free(apictimage->Cr); } if (apictimage->Cb != NULL) { free(apictimage->Cb); }#ifdef SH_MEM if ((apictimage->ximage != NULL)&&!noDisplayFlag&&shmemFlag) { if (xinfo!=NULL) XShmDetach(xinfo->display, &(apictimage->shminfo)); XDestroyImage(apictimage->ximage); shmdt(apictimage->shminfo.shmaddr); apictimage->ximage = NULL; apictimage->display = NULL; }#endif if (apictimage->display != NULL) { free(apictimage->display); } free(apictimage);}/* *-------------------------------------------------------------- * * mpegVidRsrc -- * * Parses bit stream until MB_QUANTUM number of * macroblocks have been decoded or current slice or * picture ends, whichever comes first. If the start * of a frame is encountered, the frame is time stamped * with the value passed in time_stamp. If the value * passed in buffer is not null, the video stream buffer * is set to buffer and the length of the buffer is * expected in value passed in through length. The current * video stream is set to vid_stream. If vid_stream * is passed as NULL, a new VidStream structure is created * and initialized and used as the current video stream. * * Results: * A pointer to the video stream structure used. * * Side effects: * Bit stream is irreversibly parsed. If a picture is completed, * a function is called to display the frame at the correct time. * *-------------------------------------------------------------- */VidStream *mpegVidRsrc(time_stamp, vid_stream, first, xinfo) TimeStamp time_stamp; VidStream *vid_stream; int first; XInfo *xinfo;{ unsigned int data; int i, status; /* If vid_stream is null, create new VidStream structure. */ if (vid_stream == NULL) { return NULL; } /* * If called for the first time, find start code, make sure it is a * sequence start code. */ if (first) { vid_stream->sys_layer=-1; vid_stream->num_left=0; vid_stream->leftover_bytes=0; vid_stream->seekValue=0; vid_stream->Parse_done=FALSE; next_start_code(vid_stream); /* sets curBits */ show_bits32(data); if (data != SEQ_START_CODE) { fprintf(stderr, "This is not an MPEG video stream. (%x)\n",data); DestroyVidStream(vid_stream,xinfo); return NULL; } } else {#ifdef UTIL2 vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;#else vid_stream->curBits = *vid_stream->buffer;#endif } /* Get next 32 bits (size of start codes). */ show_bits32(data); /* * Process according to start code (or parse macroblock if not a start code * at all). */ switch (data) { case SEQ_END_CODE: case 0x000001b9: /* handle ISO_11172_END_CODE too */ /* Display last frame. */ if (vid_stream->future != NULL) { vid_stream->current = vid_stream->future;#ifndef NOCONTROLS ExecuteDisplay(vid_stream, 1, xinfo);#else ExecuteDisplay(vid_stream, xinfo);#endif } /* Sequence done. Do the right thing. For right now, exit. */ if (!quietFlag) { fprintf(stderr, "\nDone!\n"); }#ifdef ANALYSIS PrintAllStats(vid_stream);#endif PrintTimeInfo(vid_stream); vid_stream->film_has_ended=TRUE;#ifdef NOCONTROLS if (loopFlag) { clear_data_stream(vid_stream); } else DestroyVidStream(vid_stream, xinfo);#endif /* !NOCONTROLS */ goto done; break; case SEQ_START_CODE: /* Sequence start code. Parse sequence header. */ if (ParseSeqHead(vid_stream,xinfo) != PARSE_OK) goto error; /* * Return after sequence start code so that application above can use * info in header. */ if (vid_stream->seekValue > 0) { SeekStream(vid_stream); } goto done; case GOP_START_CODE: /* Group of Pictures start code. Parse gop header. */ if (ParseGOP(vid_stream) != PARSE_OK) goto error; goto done; case PICTURE_START_CODE: /* Picture start code. Parse picture header and first slice header. */ status = ParsePicture(vid_stream, time_stamp); if (status == SKIP_PICTURE) { next_start_code(vid_stream); while (!next_bits(32, PICTURE_START_CODE, vid_stream)) { if (next_bits(32, GOP_START_CODE, vid_stream)) break; else if (next_bits(32, SEQ_END_CODE, vid_stream)) break; flush_bits(24); next_start_code(vid_stream); } goto done; } else if (status != PARSE_OK) goto error; if (ParseSlice(vid_stream) != PARSE_OK) goto error; break; case SEQUENCE_ERROR_CODE: flush_bits32; next_start_code(vid_stream); goto done; default: /* Check for slice start code. */ if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) { /* Slice start code. Parse slice header. */ if (ParseSlice(vid_stream) != PARSE_OK) goto error; } break; } /* Parse next MB_QUANTUM macroblocks. */ for (i = 0; i < MB_QUANTUM; i++) { /* Check to see if actually a startcode and not a macroblock. */ if (!next_bits(23, 0x00000000, vid_stream)) { /* Not start code. Parse Macroblock. */ if (ParseMacroBlock(vid_stream) != PARSE_OK) goto error;#ifdef ANALYSIS if (showmb_flag) { DoDitherImage(vid_stream);#ifndef NOCONTROLS ExecuteDisplay(vid_stream, 1, xinfo);#else ExecuteDisplay(vid_stream, xinfo);#endif /* !NOCONTROLS */ }#endif /* ANALYSIS */ } else { /* Not macroblock, actually start code. Get start code. */ next_start_code(vid_stream); show_bits32(data); /* * If start code is outside range of slice start codes, frame is * complete, display frame. */ if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) && (data != SEQUENCE_ERROR_CODE)) {#ifdef ANALYSIS EndTime(); stat_a[0].totsize += bitCountRead() - pictureSizeCount; if (showEachFlag) { PrintOneStat(); }; CollectStats();#endif DoPictureDisplay(vid_stream, xinfo); } goto done; } } /* Check if we just finished a picture on the MB_QUANTUMth macroblock */ if (next_bits(23, 0x00000000, vid_stream)) { next_start_code(vid_stream); show_bits32(data); if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {#ifdef ANALYSIS EndTime(); stat_a[0].totsize += bitCountRead() - pictureSizeCount; if (showEachFlag) { PrintOneStat(); }; CollectStats();#endif DoPictureDisplay(vid_stream, xinfo); } } /* Return pointer to video stream structure. */ goto done;error: fprintf(stderr, "Error!!!!\n"); next_start_code(vid_stream); goto done;done: return vid_stream;}/* *-------------------------------------------------------------- * * ParseSeqHead -- * * Assumes bit stream is at the begining of the sequence * header start code. Parses off the sequence header. * * Results: * Fills the vid_stream structure with values derived and * decoded from the sequence header. Allocates the pict image * structures based on the dimensions of the image space * found in the sequence header. * * Side effects: * Bit stream irreversibly parsed off. * *-------------------------------------------------------------- */static intParseSeqHead(vid_stream,xinfo) VidStream *vid_stream; XInfo *xinfo;{ unsigned int data; int i, ditherType=vid_stream->ditherType; /* Flush off sequence start code. */ flush_bits32; /* Get horizontal size of image space. */ get_bits12(data); vid_stream->h_size = data; /* Get vertical size of image space. */ get_bits12(data); vid_stream->v_size = data; /* Calculate macroblock width and height of image space. */ vid_stream->mb_width = (vid_stream->h_size + 15) / 16; vid_stream->mb_height = (vid_stream->v_size + 15) / 16;#ifndef DISABLE_DITHER /* If dither type is MBORDERED allocate ditherFlags. */ if (ditherType == MBORDERED_DITHER) { vid_stream->ditherFlags = (char *) malloc(vid_stream->mb_width*vid_stream->mb_height); }#endif /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -