📄 video_stream.c
字号:
/* Ogle - A video player * Copyright (C) 2000, 2001 Bj鰎n Englund, H錵an Hjort * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <inttypes.h>#include <signal.h>#ifdef HAVE_MLIB#include <mlib_types.h>#include <mlib_status.h>#include <mlib_sys.h>#include <mlib_video.h>#include <mlib_algebra.h>#define mlib_Init() (void)0#else#ifdef HAVE_MMX#include "mmx.h"#endif#include "c_mlib.h"#endif#include <sys/ipc.h>#include <sys/shm.h>#include <ogle/msgevents.h>#include "debug_print.h"#include "video_stream.h"#include "video_types.h"#include "video_tables.h"#include "c_getbits.h"#include "common.h"#include "timemath.h"#include "sync.h"#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endifextern void handle_events(MsgEventQ_t *q, MsgEvent_t *ev);//extern int chk_for_msg();extern MsgEventQ_t *msgq;extern int flush_to_scrid;int get_output_buffer(data_q_t *data_q, int padded_width, int padded_height, int nr_of_bufs);void remove_output_buffer(void);data_q_t *new_data_q(data_q_t **data_q_list, int padded_width, int padded_height, int nr_of_bufs);void dpy_q_put(int id, data_q_t *data_q);int output_client;int input_stream;int ctrl_data_shmid;ctrl_data_t *ctrl_data;ctrl_time_t *ctrl_time;uint8_t PTS_DTS_flags;uint64_t PTS;uint64_t DTS;int scr_nr;uint64_t last_pts;int last_scr_nr;int prev_scr_nr;int picture_has_pts;uint64_t last_pts_to_dpy;int last_scr_nr_to_dpy;static int prev_coded_temp_ref = -2;int dctstat[128];int total_pos = 0;int total_calls = 0;unsigned int debug = 0;data_q_t *data_q_head;static data_q_t *cur_data_q;int shm_ready = 0;static int shmem_flag = 1;long int frame_interval;int forced_frame_rate = -1;int nr_of_buffers = 5;//void init_out_q(int nr_of_bufs);//void setup_shm(int horiz_size, int vert_size, int nr_of_bufs);int last_temporal_ref_to_dpy = -1;int MPEG2 = 0;uint8_t intra_inverse_quantiser_matrix_changed = 1;uint8_t non_intra_inverse_quantiser_matrix_changed = 1;uint32_t stats_block_intra_nr = 0;uint32_t stats_f_intra_compute_subseq_nr = 0;uint32_t stats_f_intra_compute_first_nr = 0;sequence_t seq;picture_t pic;slice_t slice_data;#if PRAGMA_ALIGN#pragma align 32 (mb)#endifmacroblock_t ATTRIBUTE_ALIGNED(32) mb;yuv_image_t *fwd_ref_image;yuv_image_t *bwd_ref_image;yuv_image_t *dst_image;/* TODO , hack to recognize 24 fps progressive */int last_gop_had_repeat_field_progressive_frame = 0;char *program_name;int dlevel;//prototypesvoid next_start_code(void);void resync(void);void drop_to_next_picture(void);void video_sequence(void);void sequence_header(void);void sequence_extension(void);void sequence_display_extension(void);void extension_and_user_data(unsigned int i);int picture_coding_extension(void);void user_data(void);void group_of_pictures_header(void);int picture_header(void);void picture_data(void);int mpeg1_slice(void);void mpeg2_slice(void);void reset_to_default_intra_quantiser_matrix(void);void reset_to_default_non_intra_quantiser_matrix(void);void reset_to_default_quantiser_matrix(void);void user_control(macroblock_t *cur_mbs, macroblock_t *ref1_mbs, macroblock_t *ref2_mbs);void motion_comp(void);void motion_comp_add_coeff(unsigned int i);void extension_data(unsigned int i);void exit_program(int exitcode) ATTRIBUTE_NORETURN;#if PRAGMA_NORETURN#pragma does_not_return (exit_program) #endifint writer_alloc(void);void writer_free(int);int reader_alloc(void);void reader_free(int);// Not implementedvoid quant_matrix_extension(void);void picture_display_extension(void);void picture_spatial_scalable_extension(void);void picture_temporal_scalable_extension(void);void sequence_scalable_extension(void);void fprintbits(FILE *fp, unsigned int bits, uint32_t value){ int n; for(n = 0; n < bits; n++) { fprintf(fp, "%u", (value>>(bits-n-1)) & 0x1); }}int get_vlc(const vlc_table_t *table, char *func) { int numberofbits; int vlc; vlc = nextbits(16); while(1) { numberofbits = table->numberofbits; if(numberofbits == VLC_FAIL) {#if 0 fprintf(stderr, "*** get_vlc(vlc_table *table, \"%s\"): no matching " "bitstream found.\nnext 32 bits: %08x, ", func, nextbits(32)); fprintbits(stderr, 32, nextbits(32)); fprintf(stderr, "\n"); //exit_program(1);#endif return VLC_FAIL; } if(table->vlc == (vlc>>(16-numberofbits))) break; table++; } DPRINTF(3, "get_vlc(%s): len: %d, vlc: %d, val: %d\n", func, numberofbits, table->vlc, table->value); dropbits(numberofbits); return table->value;}void sighandler(int dummy){ exit_program(0);}void init_program(void){ struct sigaction sig; // Setup signal handler. // SIGINT == ctrl-c sig.sa_handler = sighandler; sig.sa_flags = 0; sigaction(SIGINT, &sig, NULL);}int msgqid = -1;//char *infilename = NULL;int main(int argc, char **argv){ int c; int output_client = 0; program_name = argv[0]; GET_DLEVEL(); /* Parse command line options */ while ((c = getopt(argc, argv, "d:r:f:m:hs")) != EOF) { switch (c) { case 'd': debug = atoi(optarg); break; case 'r': nr_of_buffers = atoi(optarg); break; case 'f': forced_frame_rate = atoi(optarg); break; case 's': shmem_flag = 0; break; case 'm': msgqid = atoi(optarg); break; case 'h': case '?': printf ("Usage: %s [-d <level] [-r <buffers>] [-s]\n\n" " -d <level> set debug level (default 0)\n" " -r <buffers> set nr of buffers (default 3)\n" " -s disable shared memory\n", program_name); return 1; } } init_program(); mlib_Init(); //init_out_q(nr_of_buffers); if(msgqid == -1) { if(optind < argc) { infilename = argv[optind]; infile = fopen(argv[optind], "r"); } else { infile = stdin; } } if(msgqid != -1) { MsgEvent_t ev; if((msgq = MsgOpen(msgqid)) == NULL) { FATAL("%s", "couldn't get message qid\n"); exit(1); } ev.type = MsgEventQRegister; ev.registercaps.capabilities = DECODE_MPEG1_VIDEO | DECODE_MPEG2_VIDEO; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { DNOTE("%s", "register capabilities failed\n"); //FIXME should we not retry/fail here? } /* ev.type = MsgEventQReqCapability; ev.reqcapability.capability = VIDEO_OUTPUT; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { fprintf(stderr, "video_decode: didn't get video_output\n"); } */ DNOTE("%s", "## req cap\n"); while(!input_stream) { if(MsgNextEvent(msgq, &ev) != -1) { switch(ev.type) { case MsgEventQGntCapability: if(ev.gntcapability.capability & VIDEO_OUTPUT) { output_client = ev.gntcapability.capclient; } else { DNOTE("%s", "got notified about capabilities not requested\n"); } break; default: handle_events(msgq, &ev); break; } } } DNOTE("%s", "got cap and stream\n"); } #ifdef GETBITSMMAP // get_next_packet(); // Really, open and mmap the FILE packet_offset = 0; packet_length = 0; buf = (uint32_t *)mmap_base; buf_size = 0; offs = 0; bits_left = 0; read_buf(); // Read first data packet and fill 'curent_word'. while( 1 ) { DPRINTF(1, "Looking for new Video Sequence\n"); video_sequence(); } #else#ifdef GETBITS32 next_word();#else fread(&buf[0], READ_SIZE, 1, infile); { uint32_t new_word1 = FROM_BE_32(buf[offs++]); uint32_t new_word2; if(offs >= READ_SIZE/4) read_buf(); new_word2 = FROM_BE_32(buf[offs++]); if(offs >= READ_SIZE/4) read_buf(); cur_word = ((uint64_t)(new_word1) << 32) | new_word2; }#endif while(!feof(infile)) { DPRINTF(1, "Looking for new Video Sequence\n"); video_sequence(); }#endif return 0;}/* 5.2.3 Definition of next_start_code() function */void next_start_code(void){ while(!bytealigned()) { GETBITS(1, "next_start_code"); } while(nextbits(24) != 0x000001) { GETBITS(8, "next_start_code"); }}void resync(void) { DPRINTF(0, "Resyncing\n"); GETBITS(8, "resync");}void drop_to_next_picture(void) { do { GETBITS(8, "drop"); next_start_code(); fprintf(stderr, "%08x\n", nextbits(32)); } while(nextbits(32) != MPEG2_VS_PICTURE_START_CODE && nextbits(32) != MPEG2_VS_GROUP_START_CODE); fprintf(stderr, "Blaha!\n");}/* 6.2.2 Video Sequence */void video_sequence(void) { next_start_code(); if(nextbits(32) != MPEG2_VS_SEQUENCE_HEADER_CODE) { resync(); return; } DPRINTF(1, "Found Sequence Header\n"); sequence_header(); DINDENT(1); if(nextbits(32) == MPEG2_VS_EXTENSION_START_CODE) { /* MPEG-2 always has an extension code right after the sequence header. */ MPEG2 = 1; sequence_extension(); DINDENT(1); do { static int lastwidth = 0; static int lastheight = 0; /* Display init */ if(!shm_ready) { cur_data_q = new_data_q(&data_q_head, seq.mb_width * 16, seq.mb_height * 16, nr_of_buffers); shm_ready = 1; lastwidth = seq.mb_width; lastheight = seq.mb_height; } else if((lastwidth != seq.mb_width) || (lastheight != seq.mb_height)) { dpy_q_put(-1, cur_data_q); cur_data_q = new_data_q(&data_q_head, seq.mb_width * 16, seq.mb_height * 16, nr_of_buffers); lastwidth = seq.mb_width; lastheight = seq.mb_height; } extension_and_user_data(0); DINDENT(1); do { if(nextbits(32) == MPEG2_VS_GROUP_START_CODE) { group_of_pictures_header(); extension_and_user_data(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -