NATIVES_SRC: media_decoder.cpp

File media_decoder.cpp, 5.2 KB (added by boyanl, 15 years ago)
Line 
1/*
2 * media_messages.cpp
3 *
4 *  Created on: Aug 18, 2009
5 *      Author: nenko
6 */
7
8#include "media_decoder.h"
9
10MediaBridge BRIDGE;
11Decoder DECODER;
12
13static int sophie_media_open(URLContext *h, const char *filename, int flags);
14static int sophie_media_read(URLContext *h, unsigned char *buf, int size);
15static int sophie_media_write(URLContext *h, unsigned char *buf, int size);
16static int64_t sophie_media_seek(URLContext *h, int64_t pos, int whence);
17static int sophie_media_close(URLContext *h);
18
19// smp = SophieMediaProtocol is misleding
20// (SMP - Simple Management Protocol, Smart Messaging Protocol)
21// changing to sophie
22URLProtocol SOPHIE_PROTOCOL = { "sophie", sophie_media_open, sophie_media_read, sophie_media_write, sophie_media_seek, sophie_media_close, };
23
24struct Sophie2MediaContext {
25        int pos;
26};
27
28//Sophie2 Media Protocol
29static int sophie_media_open(URLContext *h, const char *filename, int flags) {
30        Sophie2MediaContext *s = (Sophie2MediaContext*) av_malloc(sizeof(Sophie2MediaContext));
31        s->pos = 0;
32        //      if (!s) {
33        //              return AVERROR(ENOMEM);
34        //      }
35        h->priv_data = s;
36
37        return 0;
38}
39
40static int sophie_media_read(URLContext *h, unsigned char *buf, int size) {
41        Sophie2MediaContext *s = (Sophie2MediaContext *) h->priv_data;
42
43        int fileSize = DECODER.fileSize;
44
45        if (s->pos + size > fileSize) {
46                size = fileSize - s->pos;
47        }
48        Response res = MediaResponse::createRequestBytes(s->pos, size);
49        BRIDGE.sendResponse(res);
50        Command *cmd = BRIDGE.readCommand();
51        if (cmd->getId() == STOP_COMMAND_ID) {
52                        BRIDGE.sendResponse(BRIDGE.doStop());
53                        exit(0);
54        }
55        assert(cmd->getId() == SEND_BYTES_COMMAND);
56        SendBytesCommand *bytesCmd = (SendBytesCommand *) cmd;
57        assert(s->pos == bytesCmd->filePos);
58        assert(size == (int)bytesCmd->fileData.size());
59        int len = min(int(bytesCmd->fileData.size()), size);
60
61        memcpy(buf, (char *) &bytesCmd->fileData[0], len);
62
63        s->pos += len;
64
65        delete bytesCmd;
66
67        return len;
68}
69
70static int sophie_media_write(URLContext *h, unsigned char *buf, int size) {
71        //No writting... for now
72        return -1;
73}
74
75static int64_t sophie_media_seek(URLContext *h, int64_t pos, int whence) {
76        Sophie2MediaContext *s = (Sophie2MediaContext *) h->priv_data;
77
78        switch(whence) {
79                case SEEK_SET:
80                        s->pos = pos;
81                        break;
82                case SEEK_CUR:
83                        s->pos += pos;
84                        break;
85                case SEEK_END:
86                        s->pos = DECODER.fileSize + pos;
87                        break;
88                case AVSEEK_SIZE:
89                        return DECODER.fileSize;
90                default:
91                        assert(false);
92        }
93
94        return s->pos;
95}
96
97static int sophie_media_close(URLContext *h) {
98        Sophie2MediaContext *s = (Sophie2MediaContext*) h->priv_data;
99        av_free(s);
100
101        return 0;
102
103}
104
105Response OpenCommand::execute() {
106        fprintf(stderr, "executing open command (used to be-media_decoder.open())...\n");
107        assert(!DECODER.isOpen);
108
109        DECODER.fileSize = this->fileSize;
110        DECODER.isOpen = false;
111
112        //const char * filename = "/home/stefan/media_redesign_workspace/june_chorus.wav";//"smp:///a";
113        string filename = "sophie:///a";
114
115        av_register_all();
116        av_register_protocol(&SOPHIE_PROTOCOL);
117
118        fprintf(stderr, "opening input file...\n");
119        if (av_open_input_file(&DECODER.pFormatContext, filename.c_str(), NULL, 0, NULL) != 0) {
120                fprintf(stderr, "ERROR opening input file...\n");
121                throw runtime_error("Decoder::open - Cannot open input file!");
122        }
123
124        fprintf(stderr, "finding Streams of input file...\n");
125        if (av_find_stream_info(DECODER.pFormatContext) < 0) {
126                throw runtime_error("Decoder::open - Cannot find stream info!");
127        }
128
129        DECODER.videoStream = -1;
130        DECODER.audioStream = -1;
131        for (int i = 0; i < int(DECODER.pFormatContext->nb_streams); i++) {
132                if (DECODER.pFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
133                        DECODER.videoStream = i;
134                }
135                if (DECODER.pFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && DECODER.audioStream < 0) {
136                        DECODER.audioStream = i;
137                }
138                if (DECODER.videoStream != -1 && DECODER.audioStream != -1) {
139                        break;
140                }
141        }
142
143        if (DECODER.videoStream != -1) {
144                fprintf(stderr, "Video stream found!\n");
145                DECODER.initVideo();
146        }
147
148        if (DECODER.audioStream != -1) {
149                fprintf(stderr, "Audio stream found!\n");
150                DECODER.initAudio();
151        }
152        DECODER.isOpen = true;
153        DECODER.shifted = true;
154        DECODER.lastVideoMillis = -1;
155        DECODER.lastVideoDur = -1;
156
157        //insufficient info
158        fprintf(stderr, "\n");
159        dump_format(DECODER.pFormatContext, 0, filename.c_str(), 0);
160        return Response::createOk();
161}
162
163Response GetFrameCommand::execute() {
164        vector<byte> data;
165        int width = DECODER.pVideoCodecCtx->width;
166        int height = DECODER.pVideoCodecCtx->height;
167        DECODER.getFrame(data, timeMillis);
168        return MediaResponse::createFrame(data, width, height);
169}
170
171Response GetAudioCommand::execute() {
172        vector<byte> chunk = DECODER.getAudio(timeMillis);
173        return MediaResponse::createAudio(chunk, timeMillis);
174}
175
176Response GetInfoCommand::execute() {
177        int width = 0;
178        int height = 0;
179        AVRational frameRate;
180        bool hasAudio = false;
181        if(DECODER.videoStream >= 0) {
182                width = DECODER.pVideoCodecCtx->width;
183                height = DECODER.pVideoCodecCtx->height;
184                frameRate = DECODER.pFormatContext->streams[DECODER.videoStream]->r_frame_rate;
185        }
186        if(DECODER.audioStream >= 0) {
187                hasAudio = true;
188        }
189        int duration = DECODER.pFormatContext->duration * 1000 / AV_TIME_BASE;
190
191        return MediaResponse::createVideoInfo(width, height, duration, frameRate, hasAudio);
192
193}
194
195int main() {
196        cerr << "Starting media_decoder" << endl;
197        BRIDGE.mainLoop();
198        return 0;
199}