📄 video.c
字号:
// read video frame#include "config.h"#include <stdio.h>#ifdef HAVE_MALLOC_H#include <malloc.h>#endif#include <stdlib.h>#include <string.h>#include <unistd.h>#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "parse_es.h"#include "mpeg_hdr.h"/* sub_cc (closed captions)*/#include "../sub_cc.h"/* biCompression constant */#define BI_RGB 0L#ifdef STREAMING_LIVE_DOT_COM#include "demux_rtp.h"#endifstatic mp_mpeg_header_t picture;static int telecine=0;static float telecine_cnt=-2.5;int video_read_properties(sh_video_t *sh_video){demux_stream_t *d_video=sh_video->ds;enum { VIDEO_MPEG12, VIDEO_MPEG4, VIDEO_H264, VIDEO_OTHER} video_codec;if((d_video->demuxer->file_format == DEMUXER_TYPE_PVA) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_ES) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS && ((! sh_video->format) || (sh_video->format==0x10000001) || (sh_video->format==0x10000002))) ||// (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TY) || (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS && ((sh_video->format==0x10000001) || (sh_video->format==0x10000002)))#ifdef STREAMING_LIVE_DOT_COM || ((d_video->demuxer->file_format == DEMUXER_TYPE_RTP) && demux_is_mpeg_rtp_stream(d_video->demuxer))#endif ) video_codec = VIDEO_MPEG12; else if((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG4_ES) || ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) || ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000004)) ) video_codec = VIDEO_MPEG4; else if((d_video->demuxer->file_format == DEMUXER_TYPE_H264_ES) || ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) || ((d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005)) ) video_codec = VIDEO_H264; else video_codec = VIDEO_OTHER; // Determine image properties:switch(video_codec){ case VIDEO_OTHER: { if((d_video->demuxer->file_format == DEMUXER_TYPE_ASF) || (d_video->demuxer->file_format == DEMUXER_TYPE_AVI)) { // display info: #if 0 if(sh_video->bih->biCompression == BI_RGB && (sh_video->video.fccHandler == mmioFOURCC('D', 'I', 'B', ' ') || sh_video->video.fccHandler == mmioFOURCC('R', 'G', 'B', ' ') || sh_video->video.fccHandler == mmioFOURCC('R', 'A', 'W', ' ') || sh_video->video.fccHandler == 0)) { sh_video->format = mmioFOURCC(0, 'R', 'G', 'B') | sh_video->bih->biBitCount; } else #endif sh_video->format=sh_video->bih->biCompression; sh_video->disp_w=sh_video->bih->biWidth; sh_video->disp_h=abs(sh_video->bih->biHeight);#if 1 /* hack to support decoding of mpeg1 chunks in AVI's with libmpeg2 -- 2002 alex */ if ((sh_video->format == 0x10000001) || (sh_video->format == 0x10000002) || (sh_video->format == mmioFOURCC('m','p','g','1')) || (sh_video->format == mmioFOURCC('M','P','G','1')) || (sh_video->format == mmioFOURCC('m','p','g','2')) || (sh_video->format == mmioFOURCC('M','P','G','2')) || (sh_video->format == mmioFOURCC('m','p','e','g')) || (sh_video->format == mmioFOURCC('M','P','E','G'))) { int saved_pos, saved_type; /* demuxer pos saving is required for libavcodec mpeg decoder as it's reading the mpeg header self! */ saved_pos = d_video->buffer_pos; saved_type = d_video->demuxer->file_format; d_video->demuxer->file_format = DEMUXER_TYPE_MPEG_ES; video_read_properties(sh_video); d_video->demuxer->file_format = saved_type; d_video->buffer_pos = saved_pos;// goto mpeg_header_parser; }#endif } break; } case VIDEO_MPEG4: { int pos = 0, vop_cnt=0, units[3]; videobuf_len=0; videobuf_code_len=0; mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Start code... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); if(i<=0x11F) break; // found it! if(!i || !skip_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n"); if(!videobuffer) videobuffer=(char*)memalign(8,VIDEOBUFFER_SIZE); if(!videobuffer){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_ShMemAllocFail); return 0; } mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Layer Start code... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); mp_msg(MSGT_DECVIDEO,MSGL_V,"M4V: 0x%X\n",i); if(i>=0x120 && i<=0x12F) break; // found it! if(!i || !read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } pos = videobuf_len+4; if(!read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Layer Header\n"); return 0; } mp4_header_process_vol(&picture, &(videobuffer[pos])); mp_msg(MSGT_DECVIDEO,MSGL_V,"OK! FPS SEEMS TO BE %.3f\nSearching for Video Object Plane Start code... ", sh_video->fps);fflush(stdout); mp4_init: while(1){ int i=sync_video_packet(d_video); if(i==0x1B6) break; // found it! if(!i || !read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } pos = videobuf_len+4; if(!read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Plane Header\n"); return 0; } mp4_header_process_vop(&picture, &(videobuffer[pos])); units[vop_cnt] = picture.timeinc_unit; vop_cnt++; //mp_msg(MSGT_DECVIDEO,MSGL_V, "TYPE: %d, unit: %d\n", picture.picture_type, picture.timeinc_unit); if(!picture.fps) { int i, mn, md, mx, diff; if(vop_cnt < 3) goto mp4_init; i=0; mn = mx = units[0]; for(i=0; i<3; i++) { if(units[i] < mn) mn = units[i]; if(units[i] > mx) mx = units[i]; } md = mn; for(i=0; i<3; i++) { if((units[i] > mn) && (units[i] < mx)) md = units[i]; } mp_msg(MSGT_DECVIDEO,MSGL_V, "MIN: %d, mid: %d, max: %d\n", mn, md, mx); if(mx - md > md - mn) diff = md - mn; else diff = mx - md; if(diff > 0){ picture.fps = (picture.timeinc_resolution * 10000) / diff; mp_msg(MSGT_DECVIDEO,MSGL_V, "FPS seems to be: %d/10000, resolution: %d, delta_units: %d\n", picture.fps, picture.timeinc_resolution, diff); } } if(picture.fps) { sh_video->fps=picture.fps*0.0001f; sh_video->frametime=10000.0f/(float)picture.fps; mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %d/10000\n", picture.fps); } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n"); sh_video->format=0x10000004; break; } case VIDEO_H264: { int pos = 0; videobuf_len=0; videobuf_code_len=0; mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence parameter set... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); if((i&~0x60) == 0x107 && i != 0x107) break; // found it! if(!i || !skip_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n"); if(!videobuffer) videobuffer=(char*)memalign(8,VIDEOBUFFER_SIZE); if(!videobuffer){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_ShMemAllocFail); return 0; } pos = videobuf_len+4; if(!read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read sequence parameter set\n"); return 0; } h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos); mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for picture parameter set... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); mp_msg(MSGT_DECVIDEO,MSGL_V,"H264: 0x%X\n",i); if((i&~0x60) == 0x108 && i != 0x108) break; // found it! if(!i || !read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\nSearching for Slice... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105) break; // found it! if(!i || !read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); return 0; } } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n"); sh_video->format=0x10000005; if(picture.fps) { sh_video->fps=picture.fps*0.0001f; sh_video->frametime=10000.0f/(float)picture.fps; mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %d/10000\n", picture.fps); } break; } case VIDEO_MPEG12: {//mpeg_header_parser: // Find sequence_header first: videobuf_len=0; videobuf_code_len=0; telecine=0; telecine_cnt=-2.5; mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence header... ");fflush(stdout); while(1){ int i=sync_video_packet(d_video); if(i==0x1B3) break; // found it! if(!i || !skip_video_packet(d_video)){ if(verbose>0) mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n"); mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_MpegNoSequHdr); return 0; } } mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");// sh_video=d_video->sh;sh_video->ds=d_video;// mpeg2_init(); // ========= Read & process sequence header & extension ============ if(!videobuffer) videobuffer=(char*)memalign(8,VIDEOBUFFER_SIZE); if(!videobuffer){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_ShMemAllocFail); return 0; } if(!read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_CannotReadMpegSequHdr); return 0; } if(mp_header_process_sequence_header (&picture, &videobuffer[4])) { mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_BadMpegSequHdr); return 0; } if(sync_video_packet(d_video)==0x1B5){ // next packet is seq. ext.// videobuf_len=0; int pos=videobuf_len; if(!read_video_packet(d_video)){ mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_CannotReadMpegSequHdrEx); return 0; } if(mp_header_process_extension (&picture, &videobuffer[pos+4])) { mp_msg(MSGT_DECVIDEO,MSGL_ERR,MSGTR_BadMpegSequHdrEx); return 0; } } // printf("picture.fps=%d\n",picture.fps); // fill aspect info: switch(picture.aspect_ratio_information){ case 2: // PAL/NTSC SVCD/DVD 4:3 case 8: // PAL VCD 4:3 case 12: // NTSC VCD 4:3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -