1 /*
2 * encoder-xvid.cc --
3 *
4 * Xvid video encoder
5 */
6
7 /* This code was originally derived from a cellb reference encoder from
8 * Sun Microsystems with the following copyright:
9 *
10 * Copyright (c) Sun Microsystems, Inc. 1992, 1993. All rights reserved.
11 *
12 * License is granted to copy, to use, and to make and to use derivative
13 * works for research and evaluation purposes, provided that Sun Microsystems is
14 * acknowledged in all documentation pertaining to any such copy or derivative
15 * work. Sun Microsystems grants no other licenses expressed or implied. The
16 * Sun Microsystems trade name should not be used in any advertising without
17 * its written permission.
18 *
19 * SUN MICROSYSTEMS MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF
20 * THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is provided "as is"
21 * without express or implied warranty of any kind.
22 *
23 * These notices must be retained in any copies of any part of this software.
24 */
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include "inet.h"
29 #include "net.h"
30 #include "rtp.h"
31 #include "dct.h"
32 #include "bsd-endian.h"
33 #include "pktbuf-rtp.h"
34
35 #define MPEG4IP
36 #include "xvid/video_xvid.h"
37 #include "encoder-xvid.h"
38
39 #define HDRSIZE (sizeof(rtphdr) + sizeof(mpeg4hdr))
40
41 Mpeg4Encoder::Mpeg4Encoder () : EncoderModule ()
42 {
43 m_videoEncoder = NULL ;
44 }
45
46 static class Mpeg4EncoderClass : public TclClass {
47 public:
48 Mpeg4EncoderClass() : TclClass("Module/VideoEncoder/Pixel/MPEG4") {}
49 TclObject* create(int, const char*const*) {
50 return (new Mpeg4Encoder);
51 }
52 } mpeg4_encoder_class;
53
54 bool Mpeg4Encoder::size(int width, int height)
55 {
56 width_ = width; height_ = height;
57 if (m_videoEncoder != NULL) {
58 m_videoEncoder->Stop();
59 if (!m_videoEncoder->Init(height_, width_, realTime)) {
60 delete m_videoEncoder;
61 m_videoEncoder = NULL;
62 return false;
63 }
64 }
65 else
66 return init();
67 return true;
68 }
69
70 int Mpeg4Encoder::command(int argc, const char*const* argv)
71 {
72 // let the encoder choose the color-subsampling scheme
73 if (argc == 2 && strcmp(argv[1], "frame-format") == 0) {
74 Tcl& tcl = Tcl::instance();
75 tcl.result("420");
76 return (TCL_OK);
77 }
78
79 return (EncoderModule::command(argc, argv));
80 }
81
82 void Mpeg4Encoder::recv(Buffer* bp)
83 {
84 vf = (YuvFrame*)bp;
85 if (!samesize(vf)) {
86 errordetect = size(vf->width_, vf->height_);
87 }
88 if (!errordetect) {
89 errordetect = true;
90 return;
91 }
92
93 //decleration to prepare encoding
94 u_int32_t Ystride = width_ * height_;
95 u_int32_t UVstride = width_ * height_ / 4;
96 Yimage = vf->bp_;
97 Uimage = Yimage + Ystride;
98 Vimage = Uimage + UVstride;
99
100 errordetect = m_videoEncoder->EncodeImage(Yimage, Uimage, Vimage, width_, width_/2, keyFrame, videoMaxVopSize);
101 if (!errordetect){
102 errordetect = true;
103 return;
104 }
105 keyFrame = false;
106
107 m_videoEncoder->GetEncodedImage(&encodedImage, &encodedLen);
108
109 /*
110 FILE * fptr;
111 fptr = fopen("/home/jingye/3rd_trial/test.xvid", "a");
112 fwrite (encodedImage, sizeof(char), encodedLen, fptr);
113 fclose (fptr);
114 */
115 flush (encodedImage, encodedLen);
116 free(encodedImage);
117
118 /* testing
119 char * mychar = "/home/jingye/2nd_trial/mympeg4.dat";
120 vf->append (mychar);
121 */
122 }
123
124
125 void Mpeg4Encoder::flush (u_int8_t * mp4stream, u_int32_t len)
126 {
127 if (!pool_) {
128 printf("WARNING no buffer pool installed for encoder");
129 return;
130 }
131
132 int length = len;
133 //attn: changes have been made to rtp/rtp.h to accomodate the RTP_PT_MPEG4 macro
134 pktbuf* pb = pool_->alloc(vf->ts_, RTP_PT_MPEG4);
135 int fragsize = mtu_ - HDRSIZE;
136 short num_of_packets = (length + fragsize - 1) / fragsize; //doing a ceiling
137 u_int32_t offset = 0;
138
139 while (length > fragsize) {
140 //copying partial data
141 memcpy (&pb->data[HDRSIZE], mp4stream, fragsize);
142 //adjusting packet internal parameters
143 pb->len = mtu_;
144 rtphdr * h = (rtphdr*)pb->data;
145 mpeg4hdr * mp4head = (mpeg4hdr *)(h + 1);
146 mp4head->offset = htonl(offset);
147 mp4head->num_of_packets = htons(num_of_packets);
148 mp4head->width = htons(width_);
149 mp4head->height = htons(height_);
150 mp4head->length = htonl(len);
151 //adjust control parameter
152 offset += fragsize;
153 mp4stream += fragsize;
154 length -= fragsize;
155 //sending...
156 pb->attach();
157 target_->recv(pb);
158 pb->release ();
159 pb = pool_->alloc(vf->ts_, RTP_PT_MPEG4);
160 }
161
162 memcpy (&pb->data[HDRSIZE], mp4stream, length);
163 pb->len = length + HDRSIZE;
164 rtphdr * h = (rtphdr*)pb->data;
165 h->rh_flags |= htons(RTP_M);
166 mpeg4hdr * mp4head = (mpeg4hdr *)(h + 1);
167 mp4head->offset = htonl(offset);
168 mp4head->num_of_packets = htons(num_of_packets);
169 mp4head->width = htons(width_);
170 mp4head->height = htons(height_);
171 mp4head->length = htonl(len);
172
173 pb->attach();
174 target_->recv(pb);
175 pb->release ();
176 }
177
178
179 bool Mpeg4Encoder::init()
180 {
181 m_videoEncoder = new CXvidVideoEncoder();
182
183 if (!m_videoEncoder) {
184 return false;
185 }
186
187 realTime = true;
188 videoMaxVopSize = 128 * 1024;
189
190 if (!m_videoEncoder->Init(height_, width_, realTime)) {
191 delete m_videoEncoder;
192 m_videoEncoder = NULL;
193 return false;
194 }
195
196 keyFrame = true;
197 return true;
198 }
199
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.