📄 theora_dec.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / XIPH.org module * * GPAC 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, or (at your option) * any later version. * * GPAC 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "ogg_in.h"#ifdef GPAC_HAS_THEORA#include <theora/theora.h>typedef struct{ theora_info ti; theora_state td; theora_comment tc; ogg_packet op; u16 ES_ID; Bool has_reconfigured;} TheoraDec;#define THEORACTX() TheoraDec *ctx = (TheoraDec *) ((OGGWraper *)ifcg->privateStack)->opaquestatic GF_Err THEO_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){ ogg_packet oggpacket; GF_BitStream *bs; THEORACTX(); if (ctx->ES_ID) return GF_BAD_PARAM; if (!decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM; if (objectTypeIndication != GPAC_OGG_MEDIA_OTI) return GF_NON_COMPLIANT_BITSTREAM; if ( (decSpecInfoSize<9) || strncmp(&decSpecInfo[3], "theora", 6)) return GF_NON_COMPLIANT_BITSTREAM; oggpacket.granulepos = -1; oggpacket.b_o_s = 1; oggpacket.e_o_s = 0; oggpacket.packetno = 0; ctx->ES_ID = ES_ID; theora_info_init(&ctx->ti); theora_comment_init(&ctx->tc); bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ); while (gf_bs_available(bs)) { oggpacket.bytes = gf_bs_read_u16(bs); oggpacket.packet = malloc(sizeof(char) * oggpacket.bytes); gf_bs_read_data(bs, oggpacket.packet, oggpacket.bytes); if (theora_decode_header(&ctx->ti, &ctx->tc, &oggpacket) < 0 ) { free(oggpacket.packet); gf_bs_del(bs); return GF_NON_COMPLIANT_BITSTREAM; } free(oggpacket.packet); } theora_decode_init(&ctx->td, &ctx->ti); gf_bs_del(bs); return GF_OK;}static GF_Err THEO_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID){ THEORACTX(); if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM; theora_clear(&ctx->td); theora_info_clear(&ctx->ti); theora_comment_clear(&ctx->tc); ctx->ES_ID = 0; return GF_OK;}static GF_Err THEO_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability){ THEORACTX(); switch (capability->CapCode) { case GF_CODEC_WIDTH: capability->cap.valueInt = ctx->ti.width; break; case GF_CODEC_HEIGHT: capability->cap.valueInt = ctx->ti.height; break; case GF_CODEC_STRIDE: capability->cap.valueInt = ctx->ti.width; break; case GF_CODEC_FPS: capability->cap.valueFloat = (Float) ctx->ti.fps_numerator; capability->cap.valueFloat /= ctx->ti.fps_denominator; break; case GF_CODEC_PIXEL_FORMAT: capability->cap.valueInt = GF_PIXEL_YV12; break; case GF_CODEC_REORDER: capability->cap.valueInt = 0; break; case GF_CODEC_RESILIENT: capability->cap.valueInt = 1; break; case GF_CODEC_OUTPUT_SIZE: capability->cap.valueInt = 3*ctx->ti.width * ctx->ti.height / 2; break; case GF_CODEC_BUFFER_MIN: capability->cap.valueInt = 1; break; case GF_CODEC_BUFFER_MAX: capability->cap.valueInt = 4; break; case GF_CODEC_PADDING_BYTES: capability->cap.valueInt = 0; break; default: capability->cap.valueInt = 0; break; } return GF_OK;}static GF_Err THEO_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability){ /*return unsupported to avoid confusion by the player (like SR changing ...) */ return GF_NOT_SUPPORTED;}static GF_Err THEO_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel){ ogg_packet op; yuv_buffer yuv; u32 i; char *pYO, *pUO, *pVO; unsigned char *pYD, *pUD, *pVD; THEORACTX(); /*not using scalabilty*/ assert(ctx->ES_ID == ES_ID); op.granulepos = -1; op.b_o_s = 0; op.e_o_s = 0; op.packetno = 0; op.packet = inBuffer; op.bytes = inBufferLength; *outBufferLength = 0; if (theora_decode_packetin(&ctx->td, &op)<0) return GF_NON_COMPLIANT_BITSTREAM; if (mmlevel == GF_CODEC_LEVEL_SEEK) return GF_OK; if (theora_decode_YUVout(&ctx->td, &yuv)<0) return GF_OK; pYO = yuv.y; pUO = yuv.u; pVO = yuv.v; pYD = outBuffer; pUD = outBuffer + ctx->ti.width * ctx->ti.height; pVD = outBuffer + 5 * ctx->ti.width * ctx->ti.height / 4; for (i=0; i<(u32)yuv.y_height; i++) { memcpy(pYD, pYO, sizeof(char) * yuv.y_width); pYD += ctx->ti.width; pYO += yuv.y_stride; if (i%2) continue; memcpy(pUD, pUO, sizeof(char) * yuv.uv_width); memcpy(pVD, pVO, sizeof(char) * yuv.uv_width); pUD += ctx->ti.width/2; pVD += ctx->ti.width/2; pUO += yuv.uv_stride; pVO += yuv.uv_stride; } *outBufferLength = 3*ctx->ti.width*ctx->ti.height/2; return GF_OK;}static const char *THEO_GetCodecName(GF_BaseDecoder *dec){ return "Theora Decoder";}u32 NewTheoraDecoder(GF_BaseDecoder *ifcd){ TheoraDec *dec; GF_SAFEALLOC(dec, TheoraDec); ((OGGWraper *)ifcd->privateStack)->opaque = dec; ((OGGWraper *)ifcd->privateStack)->type = OGG_THEORA; /*setup our own interface*/ ifcd->AttachStream = THEO_AttachStream; ifcd->DetachStream = THEO_DetachStream; ifcd->GetCapabilities = THEO_GetCapabilities; ifcd->SetCapabilities = THEO_SetCapabilities; ((GF_MediaDecoder*)ifcd)->ProcessData = THEO_ProcessData; ifcd->GetName = THEO_GetCodecName; return 1;}void DeleteTheoraDecoder(GF_BaseDecoder *ifcg){ THEORACTX(); free(ctx);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -