📄 videostream.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 Opaque Industries - http://www.opaque.net/ 15.12.2003 Klaus Rechert This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; 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 "input.h"#include "method.h"#include "block.h"#include "character.h"#include "videostream.h"#include "libming.h"#include "../displaylist.h"#include "flv.h"#define VIDEO_SMOOTHING 0x01 #define VIDEO_NO_SMOOTHING 0x0#define VIDEOFRAME_BLOCK_SIZE 10struct SWFVideoStream_s{ struct SWFCharacter_s character; FLVStream *flv; FLVTag *lastTag; int lastFrame; int numFrames; unsigned int frame; int width; int height; unsigned short embedded; unsigned char codecId; unsigned char smoothingFlag; int mode; int addFrame; int framesLoaded; int firstFrame;};struct SWFVideoFrame_s{ struct SWFBlock_s block; SWFVideoStream stream; int frameNum; FLVTag tag;};int SWFVideoStream_getFrameNumber(SWFVideoFrame frame) { return frame->frameNum;}int completeSWFVideoFrame(SWFBlock block) { SWFVideoFrame frame = (SWFVideoFrame)block; SWFInput input; input = FLVTag_getPayloadInput(&frame->tag); if(input == NULL) return 4; return SWFInput_length(input) + 4;}void writeSWFVideoFrameToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { int i, ichar, len; SWFVideoFrame frame = (SWFVideoFrame)block; SWFVideoStream stream; SWFInput input; if(!block) return; input = FLVTag_getPayloadInput(&frame->tag); if(input == NULL) return; len = SWFInput_length(input); stream = frame->stream; methodWriteUInt16(CHARACTERID(stream),method, data); methodWriteUInt16(frame->frameNum, method, data); for (i = 0; i < len; i++) { ichar = SWFInput_getChar(input); method(ichar, data); }}/* * embedes a video frame in a SWFBlock object * This function reads a video frame for a FLV source and embeds it in a * SWFBlock object. */SWFBlockSWFVideoStream_getVideoFrame(SWFVideoStream stream /* associated video stream */) { SWFVideoFrame block; int frame; if(!stream->embedded) return NULL; if(stream->frame >= stream->numFrames) { SWF_warn("SWFVideoStream_getVideoFrame: frame %i, numFrames %i\n", stream->frame, stream->numFrames); return NULL; } if(stream->frame < stream->framesLoaded) return NULL; block = (SWFVideoFrame) malloc(sizeof(struct SWFVideoFrame_s)); /* If malloc failed, return NULL to signify this */ if (NULL == block) return NULL; SWFBlockInit((SWFBlock)block); BLOCK(block)->complete = completeSWFVideoFrame; BLOCK(block)->writeBlock = writeSWFVideoFrameToMethod; BLOCK(block)->dtor = NULL; BLOCK(block)->type = SWF_VIDEOFRAME; block->stream = stream; if(stream->lastTag != NULL && stream->lastFrame < stream->frame) { frame = stream->lastFrame; } else { stream->lastTag = NULL; frame = -1; } do { if(FLVStream_nextTag(stream->flv, &block->tag, stream->lastTag)) { free(block); return NULL; } stream->lastTag = &block->tag; if(block->tag.tagType == FLV_VIDEOTAG) { frame++; } } while (frame != stream->frame); block->frameNum = stream->frame; stream->lastFrame = stream->frame; stream->framesLoaded = stream->frame + 1; return (SWFBlock)block;} static int setH263CustomDimension(SWFVideoStream stream, SWFInput input, int flags) { int ichar, rshift, mask; int (*method) (SWFInput stream); SWFInput_seek(input, -1, SEEK_CUR); if(flags == 0) { method = SWFInput_getChar; rshift = 7; mask = 0xff; } else if (flags == 1) { method = SWFInput_getUInt16_BE; rshift = 15; mask = 0xffff; } else return -1; ichar = method(input); stream->width = ( (ichar << 1) & mask ); ichar = method(input); stream->width |= ( (ichar >> rshift) & mask ); stream->height = ( (ichar << 1) & mask ); ichar = method(input); stream->height |= ( (ichar >> rshift) & mask ); return 0;}static int setH263StreamDimension(SWFVideoStream stream, FLVTag *tag){ SWFInput input; int ichar, flags; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; /* skip: * pictureStartCode UB[17] 2 byte ( 1 bit remaining ) * Version UB[5] * Temporal Reference UB[8] * Picture Size UB[3] * */ SWFInput_seek(input, 2, SEEK_CUR); ichar = SWFInput_getUInt16_BE(input); /* 3-bit flag */ flags = ((0x0003 & ichar) << 1); ichar = SWFInput_getChar(input); flags |= ((0x80 & ichar) >> 7); switch(flags) { case 6: stream->width = 160; stream->height = 120; return 0; case 5: stream->width = 320; stream->height = 240; return 0; case 4: stream->width = 128; stream->height = 96; return 0; case 3: stream->width = 176; stream->height = 144; return 0; case 2: stream->width = 352; stream->height = 288; return 0; default: return setH263CustomDimension(stream, input, flags); }} static int setScreenStreamDimension(SWFVideoStream stream, FLVTag *tag) { unsigned int ui16 = 0; int ic; SWFInput input; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; /* special case: skip 1 byte */ ic = SWFInput_getChar(input); ic = SWFInput_getChar(input); if(ic >= 0) ui16 = ic << 8; ic = SWFInput_getChar(input); if(ic >= 0) ui16 |= ic; stream->width = ui16 & 0x0fff; ic = SWFInput_getChar(input); if(ic >= 0) ui16 = ic << 8; ic = SWFInput_getChar(input); if(ic >= 0) ui16 |= ic; stream->height = ui16 & 0x0fff; return 0;}void writeSWFVideoStreamToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFVideoStream stream = (SWFVideoStream)block; methodWriteUInt16(CHARACTERID(stream), method, data); methodWriteUInt16(stream->numFrames, method, data); methodWriteUInt16(stream->width, method, data); methodWriteUInt16(stream->height, method, data); if(stream->embedded) { method(stream->smoothingFlag, data); method(stream->codecId, data); } /* * in case of streaming video, flags and codec id must be 0x0 * if not 0 it craches player + browser */ else { method(0x0, data); method(0x0, data); }};int completeSWFVideoStream(SWFBlock block) { return VIDEOFRAME_BLOCK_SIZE;}void destroySWFVideoStream(SWFVideoStream stream) { destroySWFCharacter((SWFCharacter) stream);}static int setVP6Dimension(SWFVideoStream stream, FLVTag *tag){ SWFInput input; int ichar; int render_x, render_y; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; ichar = SWFInput_getChar(input); if(ichar == EOF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -