123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- #include "mkv_theora_decoder.h"
- #include "../nsmkv/Lacing.h"
- #include "../nsmkv/Cluster.h"
- #include <mmsystem.h>
- int MKVDecoder::CreateVideoDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::VideoData *video_data, ifc_mkvvideodecoder **decoder)
- {
- if (!strcmp(codec_id, "V_THEORA"))
- {
- MKVTheora *theora = new MKVTheora(video_data);
- nsmkv::LacingState lacing_state;
- if (nsmkv::Lacing::GetState(nsmkv::BlockBinary::XIPH_LACING, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &lacing_state))
- {
- const uint8_t *frame;
- size_t frame_len;
- uint16_t frame_number=0;
- while (nsmkv::Lacing::GetFrame(frame_number, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &frame, &frame_len, &lacing_state))
- {
- ogg_packet packet = {const_cast<uint8_t *>(frame), (long)frame_len, (frame_number==0), 0, 0 /*-1?*/, theora->packet_number++};
- int ret = th_decode_headerin(&theora->info, &theora->comment, &theora->setup, &packet);
- if (ret < 0)
- goto bail;
- frame_number++;
- }
- theora->decoder = th_decode_alloc(&theora->info, theora->setup);
- if (!theora->decoder)
- goto bail;
- *decoder = theora;
- return CREATEDECODER_SUCCESS;
- }
- bail:
- delete theora;
- return CREATEDECODER_FAILURE;
- }
- else
- {
- return CREATEDECODER_NOT_MINE;
- }
- }
- #define CBCLASS MKVDecoder
- START_DISPATCH;
- CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
- END_DISPATCH;
- #undef CBCLASS
- MKVTheora::MKVTheora(const nsmkv::VideoData *video_data) : video_data(video_data)
- {
- th_info_init(&info);
- memset(&comment, 0, sizeof(comment));
- setup=0;
- packet_number=0;
- frame_ready=false;
- flushing=false;
- }
- int MKVTheora::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio)
- {
- if (decoder)
- {
- th_ycbcr_buffer buffer;
- if (th_decode_ycbcr_out(decoder, buffer) == 0)
- {
- *x = buffer[0].width;
- *y = buffer[0].height;
- *aspect_ratio=1.0;
- *color_format = mmioFOURCC('Y','V','1','2');
- return MKV_SUCCESS;
- }
- }
- return MKV_FAILURE;
- }
- int MKVTheora::DecodeBlock(const void *inputBuffer, size_t inputBufferBytes, uint64_t timestamp)
- {
- if (decoder)
- {
- ogg_packet packet = {(uint8_t *)inputBuffer, (long)inputBufferBytes, 0, 0, 0 -1, packet_number++};
- if (flushing)
- {
- if (th_packet_iskeyframe(&packet))
- {
- flushing=false;
- }
- else
- return MKV_FAILURE;
- }
-
- if (th_decode_packetin(decoder, &packet, 0) == 0)
- frame_ready=true;
- last_timestamp=timestamp;
- return MKV_SUCCESS;
- }
- return MKV_FAILURE;
- }
- void MKVTheora::Flush()
- {
- packet_number = 0;
- flushing=true;
- }
- int MKVTheora::GetPicture(void **data, void **decoder_data, uint64_t *timestamp)
- {
- if (decoder && frame_ready)
- {
- th_ycbcr_buffer buffer;
- if (th_decode_ycbcr_out(decoder, buffer) == 0)
- {
- planes.y.baseAddr = buffer[0].data;
- planes.y.rowBytes = buffer[0].stride;
- planes.u.baseAddr = buffer[1].data;
- planes.u.rowBytes = buffer[1].stride;
- planes.v.baseAddr = buffer[2].data;
- planes.v.rowBytes = buffer[2].stride;
- *data = &planes;
- *decoder_data = 0;
- *timestamp = last_timestamp;
- frame_ready = false;
- return MKV_SUCCESS;
- }
- }
- return MKV_FAILURE;
- }
- void MKVTheora::FreePicture(void *data, void *decoder_data)
- {
- }
- void MKVTheora::HurryUp(int state)
- {
- }
- void MKVTheora::Close()
- {
- if (decoder)
- th_decode_free(decoder);
- delete this;
- }
- #define CBCLASS MKVTheora
- START_DISPATCH;
- CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
- CB(DECODE_BLOCK, DecodeBlock)
- VCB(FLUSH, Flush)
- CB(GET_PICTURE, GetPicture)
- VCB(FREE_PICTURE, FreePicture)
- VCB(HURRY_UP, HurryUp)
- VCB(CLOSE, Close)
- END_DISPATCH;
- #undef CBCLASS
|