Merge pull request #4220 from davilla/fix3damlcodec
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / AMLCodec.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "system.h"
22
23 #include "AMLCodec.h"
24 #include "DynamicDll.h"
25
26 #include "cores/dvdplayer/DVDClock.h"
27 #include "cores/VideoRenderers/RenderFlags.h"
28 #include "cores/VideoRenderers/RenderManager.h"
29 #include "guilib/GraphicContext.h"
30 #include "settings/MediaSettings.h"
31 #include "settings/Settings.h"
32 #include "utils/AMLUtils.h"
33 #include "utils/log.h"
34 #include "utils/StringUtils.h"
35 #include "utils/TimeUtils.h"
36
37 #if defined(TARGET_ANDROID)
38 #include "android/activity/AndroidFeatures.h"
39 #include "utils/BitstreamConverter.h"
40 #endif
41
42 #include <unistd.h>
43 #include <queue>
44 #include <vector>
45 #include <signal.h>
46 #include <semaphore.h>
47 #include <fcntl.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <sys/ioctl.h>
51
52 // amcodec include
53 extern "C" {
54 #include <amcodec/codec.h>
55 }  // extern "C"
56
57 typedef struct {
58   bool          noblock;
59   int           video_pid;
60   int           video_type;
61   stream_type_t stream_type;
62   unsigned int  format;
63   unsigned int  width;
64   unsigned int  height;
65   unsigned int  rate;
66   unsigned int  extra;
67   unsigned int  status;
68   unsigned int  ratio;
69   unsigned long long ratio64;
70   void *param;
71 } aml_generic_param;
72
73 class DllLibamCodecInterface
74 {
75 public:
76   virtual ~DllLibamCodecInterface() {};
77
78   virtual int codec_init(codec_para_t *pcodec)=0;
79   virtual int codec_close(codec_para_t *pcodec)=0;
80   virtual int codec_reset(codec_para_t *pcodec)=0;
81   virtual int codec_pause(codec_para_t *pcodec)=0;
82   virtual int codec_resume(codec_para_t *pcodec)=0;
83   virtual int codec_write(codec_para_t *pcodec, void *buffer, int len)=0;
84   virtual int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts)=0;
85   virtual int codec_get_vbuf_state(codec_para_t *pcodec, struct buf_status *buf)=0;
86   virtual int codec_get_vdec_state(codec_para_t *pcodec, struct vdec_status *vdec)=0;
87
88   virtual int codec_init_cntl(codec_para_t *pcodec)=0;
89   virtual int codec_poll_cntl(codec_para_t *pcodec)=0;
90   virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0;
91   virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int avthresh)=0;
92   virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0;
93
94   // grab these from libamplayer
95   virtual int h263vld(unsigned char *inbuf, unsigned char *outbuf, int inbuf_len, int s263)=0;
96   virtual int decodeble_h263(unsigned char *buf)=0;
97
98   // grab this from amffmpeg so we do not have to load DllAvUtil
99   virtual AVRational av_d2q(double d, int max)=0;
100 };
101
102 class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
103 {
104   // libamcodec is static linked into libamplayer.so
105   DECLARE_DLL_WRAPPER(DllLibAmCodec, "libamplayer.so")
106
107   DEFINE_METHOD1(int, codec_init,               (codec_para_t *p1))
108   DEFINE_METHOD1(int, codec_close,              (codec_para_t *p1))
109   DEFINE_METHOD1(int, codec_reset,              (codec_para_t *p1))
110   DEFINE_METHOD1(int, codec_pause,              (codec_para_t *p1))
111   DEFINE_METHOD1(int, codec_resume,             (codec_para_t *p1))
112   DEFINE_METHOD3(int, codec_write,              (codec_para_t *p1, void *p2, int p3))
113   DEFINE_METHOD2(int, codec_checkin_pts,        (codec_para_t *p1, unsigned long p2))
114   DEFINE_METHOD2(int, codec_get_vbuf_state,     (codec_para_t *p1, struct buf_status * p2))
115   DEFINE_METHOD2(int, codec_get_vdec_state,     (codec_para_t *p1, struct vdec_status * p2))
116
117   DEFINE_METHOD1(int, codec_init_cntl,          (codec_para_t *p1))
118   DEFINE_METHOD1(int, codec_poll_cntl,          (codec_para_t *p1))
119   DEFINE_METHOD2(int, codec_set_cntl_mode,      (codec_para_t *p1, unsigned int p2))
120   DEFINE_METHOD2(int, codec_set_cntl_avthresh,  (codec_para_t *p1, unsigned int p2))
121   DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2))
122
123   DEFINE_METHOD4(int, h263vld,                  (unsigned char *p1, unsigned char *p2, int p3, int p4))
124   DEFINE_METHOD1(int, decodeble_h263,           (unsigned char *p1))
125
126   DEFINE_METHOD2(AVRational, av_d2q,            (double p1, int p2))
127
128   BEGIN_METHOD_RESOLVE()
129     RESOLVE_METHOD(codec_init)
130     RESOLVE_METHOD(codec_close)
131     RESOLVE_METHOD(codec_reset)
132     RESOLVE_METHOD(codec_pause)
133     RESOLVE_METHOD(codec_resume)
134     RESOLVE_METHOD(codec_write)
135     RESOLVE_METHOD(codec_checkin_pts)
136     RESOLVE_METHOD(codec_get_vbuf_state)
137     RESOLVE_METHOD(codec_get_vdec_state)
138
139     RESOLVE_METHOD(codec_init_cntl)
140     RESOLVE_METHOD(codec_poll_cntl)
141     RESOLVE_METHOD(codec_set_cntl_mode)
142     RESOLVE_METHOD(codec_set_cntl_avthresh)
143     RESOLVE_METHOD(codec_set_cntl_syncthresh)
144
145     RESOLVE_METHOD(h263vld)
146     RESOLVE_METHOD(decodeble_h263)
147
148     RESOLVE_METHOD(av_d2q)
149   END_METHOD_RESOLVE()
150
151 public:
152   void codec_init_para(aml_generic_param *p_in, codec_para_t *p_out)
153   {
154     memset(p_out, 0x00, sizeof(codec_para_t));
155
156 #ifdef TARGET_ANDROID
157     bits_writer_t bs = {0};
158
159     // we are always as large as codec_para_t from headers.
160     CBitstreamConverter::init_bits_writer(&bs, (uint8_t*)p_out, sizeof(codec_para_t), 1);
161
162     // order matters, so pay attention
163     // to codec_para_t in codec_types.h
164     CBitstreamConverter::write_bits(&bs, 32, 0);                   // CODEC_HANDLE handle
165     CBitstreamConverter::write_bits(&bs, 32, 0);                   // CODEC_HANDLE cntl_handle
166     CBitstreamConverter::write_bits(&bs, 32, 0);                   // CODEC_HANDLE sub_handle
167
168     // added in JellyBean 4.2
169     if (CAndroidFeatures::GetVersion() > 16)
170       CBitstreamConverter::write_bits(&bs, 32, 0);                 // CODEC_HANDLE audio_utils_handle
171
172     CBitstreamConverter::write_bits(&bs, 32, p_in->stream_type);   // stream_type_t stream_type
173
174     // watch these, using bit fields (which is stupid)
175     CBitstreamConverter::write_bits(&bs,  1, 1);                   // unsigned int has_video:1
176     CBitstreamConverter::write_bits(&bs,  1, 0);                   // unsigned int has_audio:1
177     CBitstreamConverter::write_bits(&bs,  1, 0);                   // unsigned int has_sub:1
178     unsigned int value =  p_in->noblock > 0 ? 1:0;
179     CBitstreamConverter::write_bits(&bs,  1, value);               // unsigned int noblock:1
180     CBitstreamConverter::write_bits(&bs, 28, 0);                   // align back to next word boundary
181
182     CBitstreamConverter::write_bits(&bs, 32, p_in->video_type);    // int video_type
183     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int audio_type
184     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int sub_type
185
186     CBitstreamConverter::write_bits(&bs, 32, p_in->video_pid);     // int video_pid
187     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int audio_pid
188     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int sub_pid
189
190     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int audio_channels
191     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int audio_samplerate
192     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int vbuf_size
193     CBitstreamConverter::write_bits(&bs, 32, 0);                   // int abuf_size
194
195     // ARM requires 8-byte alignment for 64-bit members (ratio64)
196     // and this will force am_sysinfo to be also have 8-byte alignment.
197     // Since the inclusion of audio_utils_handle for JellyBean 4.2
198     // 'naturally' aligns am_sysinfo to 8-byte, we need to compensate
199     // when we are NOT JellyBean 4.2. If these member values get changed,
200     // then make sure you check that am_sysinfo has 8-byte alignment.
201     if (CAndroidFeatures::GetVersion() < 17)
202       CBitstreamConverter::write_bits(&bs, 32, 0);
203
204     CBitstreamConverter::write_bits(&bs, 32, p_in->format);        // am_sysinfo, unsigned int format
205     CBitstreamConverter::write_bits(&bs, 32, p_in->width);         // am_sysinfo, unsigned int width
206     CBitstreamConverter::write_bits(&bs, 32, p_in->height);        // am_sysinfo, unsigned int height
207     CBitstreamConverter::write_bits(&bs, 32, p_in->rate);          // am_sysinfo, unsigned int rate
208     CBitstreamConverter::write_bits(&bs, 32, p_in->extra);         // am_sysinfo, unsigned int extra
209     CBitstreamConverter::write_bits(&bs, 32, p_in->status);        // am_sysinfo, unsigned int status
210     CBitstreamConverter::write_bits(&bs, 32, p_in->ratio);         // am_sysinfo, unsigned int ratio
211     CBitstreamConverter::write_bits(&bs, 32, (unsigned int)p_in->param); // am_sysinfo, unsigned int param
212     unsigned int lo = 0x00000000ffffffff & p_in->ratio64;
213     unsigned int hi = p_in->ratio64 >> 32;
214     CBitstreamConverter::write_bits(&bs, 32, lo);                  // am_sysinfo, unsigned long long ratio64
215     CBitstreamConverter::write_bits(&bs, 32, hi);                  // am_sysinfo, unsigned long long ratio64
216
217     // we do not care about the rest, flush and go.
218     // FYI there are 4.0 to 4.1 differences here.
219     CBitstreamConverter::flush_bits(&bs);
220     //CLog::MemDump((char*)p_out, 0xFF);
221 #else
222     // direct struct usage, we do not know which flavor
223     // so just use what we get from headers and pray.
224     p_out->has_video          = 1;
225     p_out->noblock            = p_in->noblock;
226     p_out->video_pid          = p_in->video_pid;
227     p_out->video_type         = p_in->video_type;
228     p_out->stream_type        = p_in->stream_type;
229     p_out->am_sysinfo.format  = p_in->format;
230     p_out->am_sysinfo.width   = p_in->width;
231     p_out->am_sysinfo.height  = p_in->height;
232     p_out->am_sysinfo.rate    = p_in->rate;
233     p_out->am_sysinfo.extra   = p_in->extra;
234     p_out->am_sysinfo.status  = p_in->status;
235     p_out->am_sysinfo.ratio   = p_in->ratio;
236     p_out->am_sysinfo.ratio64 = p_in->ratio64;
237     p_out->am_sysinfo.param   = p_in->param;
238 #endif
239   }
240 };
241
242 //-----------------------------------------------------------------------------------
243 //-----------------------------------------------------------------------------------
244 // AppContext - Application state
245 #define MODE_3D_DISABLE         0x00000000
246 #define MODE_3D_LR              0x00000101
247 #define MODE_3D_BT              0x00000201
248 #define MODE_3D_TO_2D_L         0x00000102
249 #define MODE_3D_TO_2D_R         0x00000902
250 #define MODE_3D_TO_2D_T         0x00000202
251 #define MODE_3D_TO_2D_B         0x00000a02
252
253 #define PTS_FREQ        90000
254 #define UNIT_FREQ       96000
255 #define AV_SYNC_THRESH  PTS_FREQ*30
256
257 #define TRICKMODE_NONE  0x00
258 #define TRICKMODE_I     0x01
259 #define TRICKMODE_FFFB  0x02
260
261 // same as AV_NOPTS_VALUE
262 #define INT64_0         INT64_C(0x8000000000000000)
263
264 #define EXTERNAL_PTS    (1)
265 #define SYNC_OUTSIDE    (2)
266
267 // missing tags
268 #define CODEC_TAG_VC_1  (0x312D4356)
269 #define CODEC_TAG_RV30  (0x30335652)
270 #define CODEC_TAG_RV40  (0x30345652)
271 #define CODEC_TAG_MJPEG (0x47504a4d)
272 #define CODEC_TAG_mjpeg (0x47504a4c)
273 #define CODEC_TAG_jpeg  (0x6765706a)
274 #define CODEC_TAG_mjpa  (0x61706a6d)
275
276 #define RW_WAIT_TIME    (20 * 1000) // 20ms
277
278 #define P_PRE           (0x02000000)
279 #define F_PRE           (0x03000000)
280 #define PLAYER_SUCCESS          (0)
281 #define PLAYER_FAILED           (-(P_PRE|0x01))
282 #define PLAYER_NOMEM            (-(P_PRE|0x02))
283 #define PLAYER_EMPTY_P          (-(P_PRE|0x03))
284
285 #define PLAYER_WR_FAILED        (-(P_PRE|0x21))
286 #define PLAYER_WR_EMPTYP        (-(P_PRE|0x22))
287 #define PLAYER_WR_FINISH        (P_PRE|0x1)
288
289 #define PLAYER_PTS_ERROR        (-(P_PRE|0x31))
290 #define PLAYER_UNSUPPORT        (-(P_PRE|0x35))
291 #define PLAYER_CHECK_CODEC_ERROR  (-(P_PRE|0x39))
292
293 #define HDR_BUF_SIZE 1024
294 typedef struct hdr_buf {
295     char *data;
296     int size;
297 } hdr_buf_t;
298
299 typedef struct am_packet {
300     AVPacket      avpkt;
301     int64_t       avpts;
302     int64_t       avdts;
303     int           avduration;
304     int           isvalid;
305     int           newflag;
306     int64_t       lastpts;
307     unsigned char *data;
308     unsigned char *buf;
309     int           data_size;
310     int           buf_size;
311     hdr_buf_t     *hdr;
312     codec_para_t  *codec;
313 } am_packet_t;
314
315 typedef enum {
316     AM_STREAM_UNKNOWN = 0,
317     AM_STREAM_TS,
318     AM_STREAM_PS,
319     AM_STREAM_ES,
320     AM_STREAM_RM,
321     AM_STREAM_AUDIO,
322     AM_STREAM_VIDEO,
323 } pstream_type;
324
325 typedef struct am_private_t
326 {
327   am_packet_t       am_pkt;
328   aml_generic_param gcodec;
329   codec_para_t      vcodec;
330
331   pstream_type      stream_type;
332   int               check_first_pts;
333
334   vformat_t         video_format;
335   int               video_pid;
336   unsigned int      video_codec_id;
337   unsigned int      video_codec_tag;
338   vdec_type_t       video_codec_type;
339   unsigned int      video_width;
340   unsigned int      video_height;
341   unsigned int      video_ratio;
342   unsigned int      video_ratio64;
343   unsigned int      video_rate;
344   unsigned int      video_rotation_degree;
345   int               flv_flag;
346   int               h263_decodable;
347   int               extrasize;
348   uint8_t           *extradata;
349   DllLibAmCodec     *m_dll;
350
351   int               dumpfile;
352   bool              dumpdemux;
353 } am_private_t;
354
355 /*************************************************************************/
356 /*************************************************************************/
357 void dumpfile_open(am_private_t *para)
358 {
359   if (para->dumpdemux)
360   {
361     static int amcodec_dumpid = 0;
362     char dump_path[128] = {0};
363     sprintf(dump_path, "/temp/dump_amcodec-%d.dat", amcodec_dumpid++);
364
365     para->dumpfile = open(dump_path, O_CREAT | O_RDWR, 0666);
366   }
367 }
368 void dumpfile_close(am_private_t *para)
369 {
370   if (para->dumpdemux && para->dumpfile != -1)
371     close(para->dumpfile), para->dumpfile = -1;
372 }
373 void dumpfile_write(am_private_t *para, void* buf, int bufsiz)
374 {
375   if (!buf)
376   {
377     CLog::Log(LOGERROR, "dumpfile_write: wtf ? buf is null, bufsiz(%d)", bufsiz);
378     return;
379   }
380
381   if (para->dumpdemux && para->dumpfile != -1)
382     write(para->dumpfile, buf, bufsiz);
383 }
384
385 /*************************************************************************/
386 /*************************************************************************/
387 static int64_t get_pts_video()
388 {
389   int fd = open("/sys/class/tsync/pts_video", O_RDONLY);
390   if (fd >= 0)
391   {
392     char pts_str[16];
393     int size = read(fd, pts_str, sizeof(pts_str));
394     close(fd);
395     if (size > 0)
396     {
397       unsigned long pts = strtoul(pts_str, NULL, 16);
398       return pts;
399     }
400   }
401
402   CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error");
403   return -1;
404 }
405
406 static int set_pts_pcrscr(int64_t value)
407 {
408   int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY);
409   if (fd >= 0)
410   {
411     char pts_str[64];
412     unsigned long pts = (unsigned long)value;
413     sprintf(pts_str, "0x%lx", pts);
414     write(fd, pts_str, strlen(pts_str));
415     close(fd);
416     return 0;
417   }
418
419   CLog::Log(LOGERROR, "set_pts_pcrscr: open pts_pcrscr error");
420   return -1;
421 }
422
423 static vformat_t codecid_to_vformat(enum AVCodecID id)
424 {
425   vformat_t format;
426   switch (id)
427   {
428     case AV_CODEC_ID_MPEG1VIDEO:
429     case AV_CODEC_ID_MPEG2VIDEO:
430     case AV_CODEC_ID_MPEG2VIDEO_XVMC:
431       format = VFORMAT_MPEG12;
432       break;
433     case AV_CODEC_ID_H263:
434     case AV_CODEC_ID_MPEG4:
435     case AV_CODEC_ID_H263P:
436     case AV_CODEC_ID_H263I:
437     case AV_CODEC_ID_MSMPEG4V2:
438     case AV_CODEC_ID_MSMPEG4V3:
439     case AV_CODEC_ID_FLV1:
440       format = VFORMAT_MPEG4;
441       break;
442     case AV_CODEC_ID_RV10:
443     case AV_CODEC_ID_RV20:
444     case AV_CODEC_ID_RV30:
445     case AV_CODEC_ID_RV40:
446       format = VFORMAT_REAL;
447       break;
448     case AV_CODEC_ID_H264:
449       format = VFORMAT_H264;
450       break;
451     /*
452     case AV_CODEC_ID_H264MVC:
453       // H264 Multiview Video Coding (3d blurays)
454       format = VFORMAT_H264MVC;
455       break;
456     */
457     case AV_CODEC_ID_MJPEG:
458       format = VFORMAT_MJPEG;
459       break;
460     case AV_CODEC_ID_VC1:
461     case AV_CODEC_ID_WMV3:
462       format = VFORMAT_VC1;
463       break;
464     case AV_CODEC_ID_AVS:
465     case AV_CODEC_ID_CAVS:
466       format = VFORMAT_AVS;
467       break;
468
469     default:
470       format = VFORMAT_UNSUPPORT;
471       break;
472   }
473
474   CLog::Log(LOGDEBUG, "codecid_to_vformat, id(%d) -> vformat(%d)", (int)id, format);
475   return format;
476 }
477
478 static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag)
479 {
480   vdec_type_t dec_type;
481   switch (codec_tag)
482   {
483     case CODEC_TAG_MJPEG:
484     case CODEC_TAG_mjpeg:
485     case CODEC_TAG_jpeg:
486     case CODEC_TAG_mjpa:
487       // mjpeg
488       dec_type = VIDEO_DEC_FORMAT_MJPEG;
489       break;
490     case CODEC_TAG_XVID:
491     case CODEC_TAG_xvid:
492     case CODEC_TAG_XVIX:
493       // xvid
494       dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
495       break;
496     case CODEC_TAG_COL1:
497     case CODEC_TAG_DIV3:
498     case CODEC_TAG_MP43:
499       // divx3.11
500       dec_type = VIDEO_DEC_FORMAT_MPEG4_3;
501       break;
502     case CODEC_TAG_DIV4:
503     case CODEC_TAG_DIVX:
504       // divx4
505       dec_type = VIDEO_DEC_FORMAT_MPEG4_4;
506       break;
507     case CODEC_TAG_DIV5:
508     case CODEC_TAG_DX50:
509     case CODEC_TAG_M4S2:
510     case CODEC_TAG_FMP4:
511       // divx5
512       dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
513       break;
514     case CODEC_TAG_DIV6:
515       // divx6
516       dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
517       break;
518     case CODEC_TAG_MP4V:
519     case CODEC_TAG_RMP4:
520     case CODEC_TAG_MPG4:
521     case CODEC_TAG_mp4v:
522     case AV_CODEC_ID_MPEG4:
523       // mp4
524       dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
525       break;
526     case AV_CODEC_ID_H263:
527     case CODEC_TAG_H263:
528     case CODEC_TAG_h263:
529     case CODEC_TAG_s263:
530     case CODEC_TAG_F263:
531       // h263
532       dec_type = VIDEO_DEC_FORMAT_H263;
533       break;
534     case CODEC_TAG_AVC1:
535     case CODEC_TAG_avc1:
536     case CODEC_TAG_H264:
537     case CODEC_TAG_h264:
538     case AV_CODEC_ID_H264:
539       // h264
540       dec_type = VIDEO_DEC_FORMAT_H264;
541       break;
542     /*
543     case AV_CODEC_ID_H264MVC:
544       dec_type = VIDEO_DEC_FORMAT_H264;
545       break;
546     */
547     case AV_CODEC_ID_RV30:
548     case CODEC_TAG_RV30:
549       // realmedia 3
550       dec_type = VIDEO_DEC_FORMAT_REAL_8;
551       break;
552     case AV_CODEC_ID_RV40:
553     case CODEC_TAG_RV40:
554       // realmedia 4
555       dec_type = VIDEO_DEC_FORMAT_REAL_9;
556       break;
557     case CODEC_TAG_WMV3:
558       // wmv3
559       dec_type = VIDEO_DEC_FORMAT_WMV3;
560       break;
561     case AV_CODEC_ID_VC1:
562     case CODEC_TAG_VC_1:
563     case CODEC_TAG_WVC1:
564     case CODEC_TAG_WMVA:
565       // vc1
566       dec_type = VIDEO_DEC_FORMAT_WVC1;
567       break;
568     case AV_CODEC_ID_VP6F:
569       // vp6
570       dec_type = VIDEO_DEC_FORMAT_SW;
571       break;
572     case AV_CODEC_ID_CAVS:
573     case AV_CODEC_ID_AVS:
574       // avs
575       dec_type = VIDEO_DEC_FORMAT_AVS;
576       break;
577     default:
578       dec_type = VIDEO_DEC_FORMAT_UNKNOW;
579       break;
580   }
581
582   CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, codec_tag(%d) -> vdec_type(%d)", codec_tag, dec_type);
583   return dec_type;
584 }
585
586 static void am_packet_init(am_packet_t *pkt)
587 {
588   memset(&pkt->avpkt, 0, sizeof(AVPacket));
589   pkt->avpts      = 0;
590   pkt->avdts      = 0;
591   pkt->avduration = 0;
592   pkt->isvalid    = 0;
593   pkt->newflag    = 0;
594   pkt->lastpts    = 0;
595   pkt->data       = NULL;
596   pkt->buf        = NULL;
597   pkt->data_size  = 0;
598   pkt->buf_size   = 0;
599   pkt->hdr        = NULL;
600   pkt->codec      = NULL;
601 }
602
603 void am_packet_release(am_packet_t *pkt)
604 {
605   if (pkt->buf != NULL)
606     free(pkt->buf), pkt->buf= NULL;
607   if (pkt->hdr != NULL)
608   {
609     if (pkt->hdr->data != NULL)
610       free(pkt->hdr->data), pkt->hdr->data = NULL;
611     free(pkt->hdr), pkt->hdr = NULL;
612   }
613
614   pkt->codec = NULL;
615 }
616
617 int check_in_pts(am_private_t *para, am_packet_t *pkt)
618 {
619     int last_duration = 0;
620     static int last_v_duration = 0;
621     int64_t pts = 0;
622
623     last_duration = last_v_duration;
624
625     if (para->stream_type == AM_STREAM_ES) {
626         if ((int64_t)INT64_0 != pkt->avpts) {
627             pts = pkt->avpts;
628
629             if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
630                 CLog::Log(LOGDEBUG, "ERROR check in pts error!");
631                 return PLAYER_PTS_ERROR;
632             }
633
634         } else if ((int64_t)INT64_0 != pkt->avdts) {
635             pts = pkt->avdts * last_duration;
636
637             if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
638                 CLog::Log(LOGDEBUG, "ERROR check in dts error!");
639                 return PLAYER_PTS_ERROR;
640             }
641
642             last_v_duration = pkt->avduration ? pkt->avduration : 1;
643         } else {
644             if (!para->check_first_pts) {
645                 if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) {
646                     CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!");
647                     return PLAYER_PTS_ERROR;
648                 }
649             }
650         }
651         if (!para->check_first_pts) {
652             para->check_first_pts = 1;
653         }
654     }
655     if (pts > 0)
656       pkt->lastpts = pts;
657
658     return PLAYER_SUCCESS;
659 }
660
661 static int write_header(am_private_t *para, am_packet_t *pkt)
662 {
663     int write_bytes = 0, len = 0;
664
665     if (pkt->hdr && pkt->hdr->size > 0) {
666         if ((NULL == pkt->codec) || (NULL == pkt->hdr->data)) {
667             CLog::Log(LOGDEBUG, "[write_header]codec null!");
668             return PLAYER_EMPTY_P;
669         }
670         //some wvc1 es data not need to add header
671         if (para->video_format == VFORMAT_VC1 && para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
672             if ((pkt->data) && (pkt->data_size >= 4)
673               && (pkt->data[0] == 0) && (pkt->data[1] == 0)
674               && (pkt->data[2] == 1) && (pkt->data[3] == 0xd || pkt->data[3] == 0xf)) {
675                 return PLAYER_SUCCESS;
676             }
677         }
678         while (1) {
679             write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len);
680             if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) {
681                 if (-errno != AVERROR(EAGAIN)) {
682                     CLog::Log(LOGDEBUG, "ERROR:write header failed!");
683                     return PLAYER_WR_FAILED;
684                 } else {
685                     continue;
686                 }
687             } else {
688                 dumpfile_write(para, pkt->hdr->data, write_bytes);
689                 len += write_bytes;
690                 if (len == pkt->hdr->size) {
691                     break;
692                 }
693             }
694         }
695     }
696     return PLAYER_SUCCESS;
697 }
698
699 int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt)
700 {
701     return 1;
702 }
703
704 int write_av_packet(am_private_t *para, am_packet_t *pkt)
705 {
706   //CLog::Log(LOGDEBUG, "write_av_packet, pkt->isvalid(%d), pkt->data(%p), pkt->data_size(%d)",
707   //  pkt->isvalid, pkt->data, pkt->data_size);
708
709     int write_bytes = 0, len = 0, ret;
710     unsigned char *buf;
711     int size;
712
713     // do we need to check in pts or write the header ?
714     if (pkt->newflag) {
715         if (pkt->isvalid) {
716             ret = check_in_pts(para, pkt);
717             if (ret != PLAYER_SUCCESS) {
718                 CLog::Log(LOGDEBUG, "check in pts failed");
719                 return PLAYER_WR_FAILED;
720             }
721         }
722         if (write_header(para, pkt) == PLAYER_WR_FAILED) {
723             CLog::Log(LOGDEBUG, "[%s]write header failed!", __FUNCTION__);
724             return PLAYER_WR_FAILED;
725         }
726         pkt->newflag = 0;
727     }
728         
729     buf = pkt->data;
730     size = pkt->data_size ;
731     if (size == 0 && pkt->isvalid) {
732         pkt->isvalid = 0;
733         pkt->data_size = 0;
734     }
735
736     while (size > 0 && pkt->isvalid) {
737         write_bytes = para->m_dll->codec_write(pkt->codec, buf, size);
738         if (write_bytes < 0 || write_bytes > size) {
739             CLog::Log(LOGDEBUG, "write codec data failed, write_bytes(%d), errno(%d), size(%d)", write_bytes, errno, size);
740             if (-errno != AVERROR(EAGAIN)) {
741                 CLog::Log(LOGDEBUG, "write codec data failed!");
742                 return PLAYER_WR_FAILED;
743             } else {
744                 // adjust for any data we already wrote into codec.
745                 // we sleep a bit then exit as we will get called again
746                 // with the same pkt because pkt->isvalid has not been cleared.
747                 pkt->data += len;
748                 pkt->data_size -= len;
749                 usleep(RW_WAIT_TIME);
750                 CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME), len(%d)", len);
751                 return PLAYER_SUCCESS;
752             }
753         } else {
754             dumpfile_write(para, buf, write_bytes);
755             // keep track of what we write into codec from this pkt
756             // in case we get hit with EAGAIN.
757             len += write_bytes;
758             if (len == pkt->data_size) {
759                 pkt->isvalid = 0;
760                 pkt->data_size = 0;
761                 break;
762             } else if (len < pkt->data_size) {
763                 buf += write_bytes;
764                 size -= write_bytes;
765             } else {
766                 // writing more that we should is a failure.
767                 return PLAYER_WR_FAILED;
768             }
769         }
770     }
771
772     return PLAYER_SUCCESS;
773 }
774
775 /*************************************************************************/
776 static int m4s2_dx50_mp4v_add_header(unsigned char *buf, int size,  am_packet_t *pkt)
777 {
778     if (size > pkt->hdr->size) {
779         free(pkt->hdr->data), pkt->hdr->data = NULL;
780         pkt->hdr->size = 0;
781
782         pkt->hdr->data = (char*)malloc(size);
783         if (!pkt->hdr->data) {
784             CLog::Log(LOGDEBUG, "[m4s2_dx50_add_header] NOMEM!");
785             return PLAYER_FAILED;
786         }
787     }
788
789     pkt->hdr->size = size;
790     memcpy(pkt->hdr->data, buf, size);
791
792     return PLAYER_SUCCESS;
793 }
794
795 static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt)
796 {
797     CLog::Log(LOGDEBUG, "m4s2_dx50_mp4v_write_header");
798     int ret = m4s2_dx50_mp4v_add_header(para->extradata, para->extrasize, pkt);
799     if (ret == PLAYER_SUCCESS) {
800         if (1) {
801             pkt->codec = &para->vcodec;
802         } else {
803             CLog::Log(LOGDEBUG, "[m4s2_dx50_mp4v_add_header]invalid video codec!");
804             return PLAYER_EMPTY_P;
805         }
806         pkt->newflag = 1;
807         ret = write_av_packet(para, pkt);
808     }
809     return ret;
810 }
811
812 static int mjpeg_data_prefeeding(am_packet_t *pkt)
813 {
814     const unsigned char mjpeg_addon_data[] = {
815         0xff, 0xd8, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
816         0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
817         0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01,
818         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
819         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10,
820         0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
821         0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
822         0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1,
823         0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
824         0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
825         0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
826         0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
827         0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
828         0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
829         0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
830         0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,
831         0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
832         0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
833         0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01,
834         0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
835         0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
836         0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
837         0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
838         0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
839         0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
840         0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
841         0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
842         0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
843         0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
844         0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
845         0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
846         0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
847         0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
848     };
849
850     if (pkt->hdr->data) {
851         memcpy(pkt->hdr->data, &mjpeg_addon_data, sizeof(mjpeg_addon_data));
852         pkt->hdr->size = sizeof(mjpeg_addon_data);
853     } else {
854         CLog::Log(LOGDEBUG, "[mjpeg_data_prefeeding]No enough memory!");
855         return PLAYER_FAILED;
856     }
857     return PLAYER_SUCCESS;
858 }
859
860 static int mjpeg_write_header(am_private_t *para, am_packet_t *pkt)
861 {
862     mjpeg_data_prefeeding(pkt);
863     if (1) {
864         pkt->codec = &para->vcodec;
865     } else {
866         CLog::Log(LOGDEBUG, "[mjpeg_write_header]invalid codec!");
867         return PLAYER_EMPTY_P;
868     }
869     pkt->newflag = 1;
870     write_av_packet(para, pkt);
871     return PLAYER_SUCCESS;
872 }
873
874 static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h)
875 {
876     unsigned i = (w << 12) | (h & 0xfff);
877     unsigned char divx311_add[10] = {
878         0x00, 0x00, 0x00, 0x01,
879         0x20, 0x00, 0x00, 0x00,
880         0x00, 0x00
881     };
882     divx311_add[5] = (i >> 16) & 0xff;
883     divx311_add[6] = (i >> 8) & 0xff;
884     divx311_add[7] = i & 0xff;
885
886     if (pkt->hdr->data) {
887         memcpy(pkt->hdr->data, divx311_add, sizeof(divx311_add));
888         pkt->hdr->size = sizeof(divx311_add);
889     } else {
890         CLog::Log(LOGDEBUG, "[divx3_data_prefeeding]No enough memory!");
891         return PLAYER_FAILED;
892     }
893     return PLAYER_SUCCESS;
894 }
895
896 static int divx3_write_header(am_private_t *para, am_packet_t *pkt)
897 {
898     CLog::Log(LOGDEBUG, "divx3_write_header");
899     divx3_data_prefeeding(pkt, para->video_width, para->video_height);
900     if (1) {
901         pkt->codec = &para->vcodec;
902     } else {
903         CLog::Log(LOGDEBUG, "[divx3_write_header]invalid codec!");
904         return PLAYER_EMPTY_P;
905     }
906     pkt->newflag = 1;
907     write_av_packet(para, pkt);
908     return PLAYER_SUCCESS;
909 }
910
911 static int h264_add_header(unsigned char *buf, int size, am_packet_t *pkt)
912 {
913     // h264 annex-b
914           if ((buf[0]==0 && buf[1]==0 && buf[2]==0 && buf[3]==1) && size < HDR_BUF_SIZE) {
915         CLog::Log(LOGDEBUG, "add four byte NAL 264 header in stream before header len=%d",size);
916         memcpy(pkt->hdr->data, buf, size);
917         pkt->hdr->size = size;
918         return PLAYER_SUCCESS;
919     }
920
921     if ((buf[0]==0 && buf[1]==0 && buf[2]==1) && size < HDR_BUF_SIZE) {
922         CLog::Log(LOGDEBUG, "add three byte NAL 264 header in stream before header len=%d",size);
923         memcpy(pkt->hdr->data, buf, size);
924         pkt->hdr->size = size;
925         return PLAYER_SUCCESS;
926     }
927
928     return PLAYER_FAILED;
929 }
930 static int h264_write_header(am_private_t *para, am_packet_t *pkt)
931 {
932     // CLog::Log(LOGDEBUG, "h264_write_header");
933     int ret = -1;
934
935     ret = h264_add_header(para->extradata, para->extrasize, pkt);
936     if (ret == PLAYER_SUCCESS) {
937         //if (ctx->vcodec) {
938         if (1) {
939             pkt->codec = &para->vcodec;
940         } else {
941             //CLog::Log(LOGDEBUG, "[pre_header_feeding]invalid video codec!");
942             return PLAYER_EMPTY_P;
943         }
944
945         pkt->newflag = 1;
946         ret = write_av_packet(para, pkt);
947     }
948     return ret;
949 }
950
951 static int wmv3_write_header(am_private_t *para, am_packet_t *pkt)
952 {
953     CLog::Log(LOGDEBUG, "wmv3_write_header");
954     unsigned i, check_sum = 0;
955     unsigned data_len = para->extrasize + 4;
956
957     pkt->hdr->data[0] = 0;
958     pkt->hdr->data[1] = 0;
959     pkt->hdr->data[2] = 1;
960     pkt->hdr->data[3] = 0x10;
961
962     pkt->hdr->data[4] = 0;
963     pkt->hdr->data[5] = (data_len >> 16) & 0xff;
964     pkt->hdr->data[6] = 0x88;
965     pkt->hdr->data[7] = (data_len >> 8) & 0xff;
966     pkt->hdr->data[8] = data_len & 0xff;
967     pkt->hdr->data[9] = 0x88;
968
969     pkt->hdr->data[10] = 0xff;
970     pkt->hdr->data[11] = 0xff;
971     pkt->hdr->data[12] = 0x88;
972     pkt->hdr->data[13] = 0xff;
973     pkt->hdr->data[14] = 0xff;
974     pkt->hdr->data[15] = 0x88;
975
976     for (i = 4 ; i < 16 ; i++) {
977         check_sum += pkt->hdr->data[i];
978     }
979
980     pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
981     pkt->hdr->data[17] =  check_sum & 0xff;
982     pkt->hdr->data[18] = 0x88;
983     pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
984     pkt->hdr->data[20] =  check_sum & 0xff;
985     pkt->hdr->data[21] = 0x88;
986
987     pkt->hdr->data[22] = (para->video_width >> 8) & 0xff;
988     pkt->hdr->data[23] =  para->video_width & 0xff;
989     pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
990     pkt->hdr->data[25] =  para->video_height & 0xff;
991
992     memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
993     pkt->hdr->size = para->extrasize + 26;
994     if (1) {
995         pkt->codec = &para->vcodec;
996     } else {
997         CLog::Log(LOGDEBUG, "[wmv3_write_header]invalid codec!");
998         return PLAYER_EMPTY_P;
999     }
1000     pkt->newflag = 1;
1001     return write_av_packet(para, pkt);
1002 }
1003
1004 static int wvc1_write_header(am_private_t *para, am_packet_t *pkt)
1005 {
1006     CLog::Log(LOGDEBUG, "wvc1_write_header");
1007     memcpy(pkt->hdr->data, para->extradata + 1, para->extrasize - 1);
1008     pkt->hdr->size = para->extrasize - 1;
1009     if (1) {
1010         pkt->codec = &para->vcodec;
1011     } else {
1012         CLog::Log(LOGDEBUG, "[wvc1_write_header]invalid codec!");
1013         return PLAYER_EMPTY_P;
1014     }
1015     pkt->newflag = 1;
1016     return write_av_packet(para, pkt);
1017 }
1018
1019 static int mpeg_add_header(am_private_t *para, am_packet_t *pkt)
1020 {
1021     CLog::Log(LOGDEBUG, "mpeg_add_header");
1022 #define STUFF_BYTES_LENGTH     (256)
1023     int size;
1024     unsigned char packet_wrapper[] = {
1025         0x00, 0x00, 0x01, 0xe0,
1026         0x00, 0x00,                                /* pes packet length */
1027         0x81, 0xc0, 0x0d,
1028         0x20, 0x00, 0x00, 0x00, 0x00, /* PTS */
1029         0x1f, 0xff, 0xff, 0xff, 0xff, /* DTS */
1030         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1031     };
1032
1033     size = para->extrasize + sizeof(packet_wrapper);
1034     packet_wrapper[4] = size >> 8 ;
1035     packet_wrapper[5] = size & 0xff ;
1036     memcpy(pkt->hdr->data, packet_wrapper, sizeof(packet_wrapper));
1037     size = sizeof(packet_wrapper);
1038     //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper size=%d\n",__LINE__,size);
1039     memcpy(pkt->hdr->data + size, para->extradata, para->extrasize);
1040     size += para->extrasize;
1041     //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper+seq size=%d\n",__LINE__,size);
1042     memset(pkt->hdr->data + size, 0xff, STUFF_BYTES_LENGTH);
1043     size += STUFF_BYTES_LENGTH;
1044     pkt->hdr->size = size;
1045     //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]hdr_size=%d\n",__LINE__,size);
1046     if (1) {
1047         pkt->codec = &para->vcodec;
1048     } else {
1049         CLog::Log(LOGDEBUG, "[mpeg_add_header]invalid codec!");
1050         return PLAYER_EMPTY_P;
1051     }
1052
1053     pkt->newflag = 1;
1054     return write_av_packet(para, pkt);
1055 }
1056
1057 int pre_header_feeding(am_private_t *para, am_packet_t *pkt)
1058 {
1059     int ret;
1060     if (para->stream_type == AM_STREAM_ES) {
1061         if (pkt->hdr == NULL) {
1062             pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1063             pkt->hdr->data = (char *)malloc(HDR_BUF_SIZE);
1064             if (!pkt->hdr->data) {
1065                 //CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
1066                 return PLAYER_NOMEM;
1067             }
1068         }
1069
1070         if (VFORMAT_H264 == para->video_format /*|| VFORMAT_H264MVC == para->video_format*/) {
1071             ret = h264_write_header(para, pkt);
1072             if (ret != PLAYER_SUCCESS) {
1073                 return ret;
1074             }
1075         } else if ((VFORMAT_MPEG4 == para->video_format) && (VIDEO_DEC_FORMAT_MPEG4_3 == para->video_codec_type)) {
1076             ret = divx3_write_header(para, pkt);
1077             if (ret != PLAYER_SUCCESS) {
1078                 return ret;
1079             }
1080         } else if ((CODEC_TAG_M4S2 == para->video_codec_tag)
1081                 || (CODEC_TAG_DX50 == para->video_codec_tag)
1082                 || (CODEC_TAG_mp4v == para->video_codec_tag)) {
1083             ret = m4s2_dx50_mp4v_write_header(para, pkt);
1084             if (ret != PLAYER_SUCCESS) {
1085                 return ret;
1086             }
1087         /*
1088         } else if ((AVI_FILE == para->file_type)
1089                 && (VIDEO_DEC_FORMAT_MPEG4_3 != para->vstream_info.video_codec_type)
1090                 && (VFORMAT_H264 != para->vstream_info.video_format)
1091                 && (VFORMAT_VC1 != para->vstream_info.video_format)) {
1092             ret = avi_write_header(para);
1093             if (ret != PLAYER_SUCCESS) {
1094                 return ret;
1095             }
1096         */
1097         } else if (CODEC_TAG_WMV3 == para->video_codec_tag) {
1098             CLog::Log(LOGDEBUG, "CODEC_TAG_WMV3 == para->video_codec_tag");
1099             ret = wmv3_write_header(para, pkt);
1100             if (ret != PLAYER_SUCCESS) {
1101                 return ret;
1102             }
1103         } else if ((CODEC_TAG_WVC1 == para->video_codec_tag)
1104                 || (CODEC_TAG_VC_1 == para->video_codec_tag)
1105                 || (CODEC_TAG_WMVA == para->video_codec_tag)) {
1106             CLog::Log(LOGDEBUG, "CODEC_TAG_WVC1 == para->video_codec_tag");
1107             ret = wvc1_write_header(para, pkt);
1108             if (ret != PLAYER_SUCCESS) {
1109                 return ret;
1110             }
1111         /*
1112         } else if ((MKV_FILE == para->file_type) &&
1113                   ((VFORMAT_MPEG4 == para->vstream_info.video_format)
1114                 || (VFORMAT_MPEG12 == para->vstream_info.video_format))) {
1115             ret = mkv_write_header(para, pkt);
1116             if (ret != PLAYER_SUCCESS) {
1117                 return ret;
1118             }
1119         */
1120         } else if (VFORMAT_MJPEG == para->video_format) {
1121             ret = mjpeg_write_header(para, pkt);
1122             if (ret != PLAYER_SUCCESS) {
1123                 return ret;
1124             }
1125         }
1126
1127         if (pkt->hdr) {
1128             if (pkt->hdr->data) {
1129                 free(pkt->hdr->data);
1130                 pkt->hdr->data = NULL;
1131             }
1132             free(pkt->hdr);
1133             pkt->hdr = NULL;
1134         }
1135     }
1136     else if (para->stream_type == AM_STREAM_PS) {
1137         if (pkt->hdr == NULL) {
1138             pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1139             pkt->hdr->data = (char*)malloc(HDR_BUF_SIZE);
1140             if (!pkt->hdr->data) {
1141                 CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
1142                 return PLAYER_NOMEM;
1143             }
1144         }
1145         if (( AV_CODEC_ID_MPEG1VIDEO == para->video_codec_id)
1146           || (AV_CODEC_ID_MPEG2VIDEO == para->video_codec_id)
1147           || (AV_CODEC_ID_MPEG2VIDEO_XVMC == para->video_codec_id)) {
1148             ret = mpeg_add_header(para, pkt);
1149             if (ret != PLAYER_SUCCESS) {
1150                 return ret;
1151             }
1152         }
1153         if (pkt->hdr) {
1154             if (pkt->hdr->data) {
1155                 free(pkt->hdr->data);
1156                 pkt->hdr->data = NULL;
1157             }
1158             free(pkt->hdr);
1159             pkt->hdr = NULL;
1160         }
1161     }
1162     return PLAYER_SUCCESS;
1163 }
1164
1165 int divx3_prefix(am_packet_t *pkt)
1166 {
1167 #define DIVX311_CHUNK_HEAD_SIZE 13
1168     const unsigned char divx311_chunk_prefix[DIVX311_CHUNK_HEAD_SIZE] = {
1169         0x00, 0x00, 0x00, 0x01, 0xb6, 'D', 'I', 'V', 'X', '3', '.', '1', '1'
1170     };
1171     if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1172         free(pkt->hdr->data);
1173         pkt->hdr->data = NULL;
1174     }
1175
1176     if (pkt->hdr == NULL) {
1177         pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1178         if (!pkt->hdr) {
1179             CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1180             return PLAYER_FAILED;
1181         }
1182
1183         pkt->hdr->data = NULL;
1184         pkt->hdr->size = 0;
1185     }
1186
1187     pkt->hdr->data = (char*)malloc(DIVX311_CHUNK_HEAD_SIZE + 4);
1188     if (pkt->hdr->data == NULL) {
1189         CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1190         return PLAYER_FAILED;
1191     }
1192
1193     memcpy(pkt->hdr->data, divx311_chunk_prefix, DIVX311_CHUNK_HEAD_SIZE);
1194
1195     pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 0] = (pkt->data_size >> 24) & 0xff;
1196     pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 1] = (pkt->data_size >> 16) & 0xff;
1197     pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 2] = (pkt->data_size >>  8) & 0xff;
1198     pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 3] = pkt->data_size & 0xff;
1199
1200     pkt->hdr->size = DIVX311_CHUNK_HEAD_SIZE + 4;
1201     pkt->newflag = 1;
1202
1203     return PLAYER_SUCCESS;
1204 }
1205
1206 int set_header_info(am_private_t *para)
1207 {
1208   am_packet_t *pkt = &para->am_pkt;
1209
1210   //if (pkt->newflag)
1211   {
1212     //if (pkt->hdr)
1213     //  pkt->hdr->size = 0;
1214
1215     if (para->video_format == VFORMAT_MPEG4)
1216     {
1217       if (para->video_codec_type == VIDEO_DEC_FORMAT_MPEG4_3)
1218       {
1219         return divx3_prefix(pkt);
1220       }
1221       else if (para->video_codec_type == VIDEO_DEC_FORMAT_H263)
1222       {
1223         return PLAYER_UNSUPPORT;
1224         unsigned char *vld_buf;
1225         int vld_len, vld_buf_size = para->video_width * para->video_height * 2;
1226
1227         if (!pkt->data_size) {
1228             return PLAYER_SUCCESS;
1229         }
1230
1231         if ((pkt->data[0] == 0) && (pkt->data[1] == 0) && (pkt->data[2] == 1) && (pkt->data[3] == 0xb6)) {
1232             return PLAYER_SUCCESS;
1233         }
1234
1235         vld_buf = (unsigned char*)malloc(vld_buf_size);
1236         if (!vld_buf) {
1237             return PLAYER_NOMEM;
1238         }
1239
1240         if (para->flv_flag) {
1241             vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 1);
1242         } else {
1243             if (0 == para->h263_decodable) {
1244                 para->h263_decodable = para->m_dll->decodeble_h263(pkt->data);
1245                 if (0 == para->h263_decodable) {
1246                     CLog::Log(LOGDEBUG, "[%s]h263 unsupport video and audio, exit", __FUNCTION__);
1247                     return PLAYER_UNSUPPORT;
1248                 }
1249             }
1250             vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 0);
1251         }
1252
1253         if (vld_len > 0) {
1254             if (pkt->buf) {
1255                 free(pkt->buf);
1256             }
1257             pkt->buf = vld_buf;
1258             pkt->buf_size = vld_buf_size;
1259             pkt->data = pkt->buf;
1260             pkt->data_size = vld_len;
1261         } else {
1262             free(vld_buf);
1263             pkt->data_size = 0;
1264         }
1265       }
1266     } else if (para->video_format == VFORMAT_VC1) {
1267         if (para->video_codec_type == VIDEO_DEC_FORMAT_WMV3) {
1268             unsigned i, check_sum = 0, data_len = 0;
1269
1270             if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1271                 free(pkt->hdr->data);
1272                 pkt->hdr->data = NULL;
1273             }
1274
1275             if (pkt->hdr == NULL) {
1276                 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1277                 if (!pkt->hdr) {
1278                     return PLAYER_FAILED;
1279                 }
1280
1281                 pkt->hdr->data = NULL;
1282                 pkt->hdr->size = 0;
1283             }
1284
1285             if (pkt->avpkt.flags) {
1286                 pkt->hdr->data = (char*)malloc(para->extrasize + 26 + 22);
1287                 if (pkt->hdr->data == NULL) {
1288                     return PLAYER_FAILED;
1289                 }
1290
1291                 pkt->hdr->data[0] = 0;
1292                 pkt->hdr->data[1] = 0;
1293                 pkt->hdr->data[2] = 1;
1294                 pkt->hdr->data[3] = 0x10;
1295
1296                 data_len = para->extrasize + 4;
1297                 pkt->hdr->data[4] = 0;
1298                 pkt->hdr->data[5] = (data_len >> 16) & 0xff;
1299                 pkt->hdr->data[6] = 0x88;
1300                 pkt->hdr->data[7] = (data_len >> 8) & 0xff;
1301                 pkt->hdr->data[8] =  data_len & 0xff;
1302                 pkt->hdr->data[9] = 0x88;
1303
1304                 pkt->hdr->data[10] = 0xff;
1305                 pkt->hdr->data[11] = 0xff;
1306                 pkt->hdr->data[12] = 0x88;
1307                 pkt->hdr->data[13] = 0xff;
1308                 pkt->hdr->data[14] = 0xff;
1309                 pkt->hdr->data[15] = 0x88;
1310
1311                 for (i = 4 ; i < 16 ; i++) {
1312                     check_sum += pkt->hdr->data[i];
1313                 }
1314
1315                 pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
1316                 pkt->hdr->data[17] =  check_sum & 0xff;
1317                 pkt->hdr->data[18] = 0x88;
1318                 pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
1319                 pkt->hdr->data[20] =  check_sum & 0xff;
1320                 pkt->hdr->data[21] = 0x88;
1321
1322                 pkt->hdr->data[22] = (para->video_width  >> 8) & 0xff;
1323                 pkt->hdr->data[23] =  para->video_width  & 0xff;
1324                 pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
1325                 pkt->hdr->data[25] =  para->video_height & 0xff;
1326
1327                 memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
1328
1329                 check_sum = 0;
1330                 data_len = para->extrasize + 26;
1331             } else {
1332                 pkt->hdr->data = (char*)malloc(22);
1333                 if (pkt->hdr->data == NULL) {
1334                     return PLAYER_FAILED;
1335                 }
1336             }
1337
1338             pkt->hdr->data[data_len + 0]  = 0;
1339             pkt->hdr->data[data_len + 1]  = 0;
1340             pkt->hdr->data[data_len + 2]  = 1;
1341             pkt->hdr->data[data_len + 3]  = 0xd;
1342
1343             pkt->hdr->data[data_len + 4]  = 0;
1344             pkt->hdr->data[data_len + 5]  = (pkt->data_size >> 16) & 0xff;
1345             pkt->hdr->data[data_len + 6]  = 0x88;
1346             pkt->hdr->data[data_len + 7]  = (pkt->data_size >> 8) & 0xff;
1347             pkt->hdr->data[data_len + 8]  =  pkt->data_size & 0xff;
1348             pkt->hdr->data[data_len + 9]  = 0x88;
1349
1350             pkt->hdr->data[data_len + 10] = 0xff;
1351             pkt->hdr->data[data_len + 11] = 0xff;
1352             pkt->hdr->data[data_len + 12] = 0x88;
1353             pkt->hdr->data[data_len + 13] = 0xff;
1354             pkt->hdr->data[data_len + 14] = 0xff;
1355             pkt->hdr->data[data_len + 15] = 0x88;
1356
1357             for (i = data_len + 4 ; i < data_len + 16 ; i++) {
1358                 check_sum += pkt->hdr->data[i];
1359             }
1360
1361             pkt->hdr->data[data_len + 16] = (check_sum >> 8) & 0xff;
1362             pkt->hdr->data[data_len + 17] =  check_sum & 0xff;
1363             pkt->hdr->data[data_len + 18] = 0x88;
1364             pkt->hdr->data[data_len + 19] = (check_sum >> 8) & 0xff;
1365             pkt->hdr->data[data_len + 20] =  check_sum & 0xff;
1366             pkt->hdr->data[data_len + 21] = 0x88;
1367
1368             pkt->hdr->size = data_len + 22;
1369             pkt->newflag = 1;
1370         } else if (para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
1371             if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1372                 free(pkt->hdr->data);
1373                 pkt->hdr->data = NULL;
1374             }
1375
1376             if (pkt->hdr == NULL) {
1377                 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1378                 if (!pkt->hdr) {
1379                     CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1380                     return PLAYER_FAILED;
1381                 }
1382
1383                 pkt->hdr->data = NULL;
1384                 pkt->hdr->size = 0;
1385             }
1386
1387             pkt->hdr->data = (char*)malloc(4);
1388             if (pkt->hdr->data == NULL) {
1389                 CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1390                 return PLAYER_FAILED;
1391             }
1392
1393             pkt->hdr->data[0] = 0;
1394             pkt->hdr->data[1] = 0;
1395             pkt->hdr->data[2] = 1;
1396             pkt->hdr->data[3] = 0xd;
1397             pkt->hdr->size = 4;
1398             pkt->newflag = 1;
1399         }
1400     }
1401   }
1402   return PLAYER_SUCCESS;
1403 }
1404
1405 /*************************************************************************/
1406 CAMLCodec::CAMLCodec() : CThread("CAMLCodec")
1407 {
1408   m_opened = false;
1409   am_private = new am_private_t;
1410   memset(am_private, 0, sizeof(am_private_t));
1411   m_dll = new DllLibAmCodec;
1412   m_dll->Load();
1413   am_private->m_dll = m_dll;
1414 }
1415
1416
1417 CAMLCodec::~CAMLCodec()
1418 {
1419   StopThread();
1420   delete am_private;
1421   am_private = NULL;
1422   delete m_dll, m_dll = NULL;
1423 }
1424
1425 bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
1426 {
1427 #ifdef TARGET_ANDROID
1428   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder, android version %d", CAndroidFeatures::GetVersion());
1429 #endif
1430
1431   m_speed = DVD_PLAYSPEED_NORMAL;
1432   m_1st_pts = 0;
1433   m_cur_pts = 0;
1434   m_cur_pictcnt = 0;
1435   m_old_pictcnt = 0;
1436   m_dst_rect.SetRect(0, 0, 0, 0);
1437   m_zoom = -1;
1438   m_contrast = -1;
1439   m_brightness = -1;
1440   m_vbufsize = 500000 * 2;
1441   m_start_dts = 0;
1442   m_start_pts = 0;
1443   m_hints = hints;
1444
1445   ShowMainVideo(false);
1446
1447   am_packet_init(&am_private->am_pkt);
1448   // default stream type
1449   am_private->stream_type      = AM_STREAM_ES;
1450   // handle hints.
1451   am_private->video_width      = hints.width;
1452   am_private->video_height     = hints.height;
1453   am_private->video_codec_id   = hints.codec;
1454   am_private->video_codec_tag  = hints.codec_tag;
1455   am_private->video_pid        = hints.pid;
1456
1457   // handle video ratio
1458   AVRational video_ratio       = m_dll->av_d2q(1, SHRT_MAX);
1459   //if (!hints.forced_aspect)
1460   //  video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX);
1461   am_private->video_ratio      = ((int32_t)video_ratio.num << 16) | video_ratio.den;
1462   am_private->video_ratio64    = ((int64_t)video_ratio.num << 32) | video_ratio.den;
1463
1464   // handle video rate
1465   if (hints.rfpsrate > 0 && hints.rfpsscale != 0)
1466   {
1467     // check ffmpeg r_frame_rate 1st
1468     am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate;
1469   }
1470   else if (hints.fpsrate > 0 && hints.fpsscale != 0)
1471   {
1472     // then ffmpeg avg_frame_rate next
1473     am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate;
1474   }
1475
1476   // check for 1920x1080, interlaced, 25 fps
1477   // incorrectly reported as 50 fps (yes, video_rate == 1920)
1478   if (hints.width == 1920 && am_private->video_rate == 1920)
1479   {
1480     CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1481     am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000;
1482   }
1483
1484   // check for SD h264 content incorrectly reported as 60 fsp
1485   // mp4/avi containers :(
1486   if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 1602)
1487   {
1488     CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1489     am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1490   }
1491
1492   // check for SD h264 content incorrectly reported as some form of 30 fsp
1493   // mp4/avi containers :(
1494   if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720)
1495   {
1496     if (am_private->video_rate >= 3200 && am_private->video_rate <= 3210)
1497     {
1498       CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1499       am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1500     }
1501   }
1502
1503   // handle orientation
1504   am_private->video_rotation_degree = 0;
1505   if (hints.orientation == 90)
1506     am_private->video_rotation_degree = 1;
1507   else if (hints.orientation == 180)
1508     am_private->video_rotation_degree = 2;
1509   else if (hints.orientation == 270)
1510     am_private->video_rotation_degree = 3;
1511   // handle extradata
1512   am_private->video_format      = codecid_to_vformat(hints.codec);
1513   switch (am_private->video_format)
1514   {
1515     default:
1516       am_private->extrasize       = hints.extrasize;
1517       am_private->extradata       = (uint8_t*)malloc(hints.extrasize);
1518       memcpy(am_private->extradata, hints.extradata, hints.extrasize);
1519       break;
1520     case VFORMAT_REAL:
1521     case VFORMAT_MPEG12:
1522       break;
1523   }
1524
1525   if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0)
1526     am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag);
1527   else
1528     am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id);
1529
1530   am_private->flv_flag = 0;
1531   if (am_private->video_codec_id == AV_CODEC_ID_FLV1)
1532   {
1533     am_private->video_codec_tag = CODEC_TAG_F263;
1534     am_private->flv_flag = 1;
1535   }
1536
1537   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder "
1538     "hints.width(%d), hints.height(%d), hints.codec(%d), hints.codec_tag(%d), hints.pid(%d)",
1539     hints.width, hints.height, hints.codec, hints.codec_tag, hints.pid);
1540   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)",
1541     hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate);
1542   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)",
1543     hints.aspect, video_ratio.num, video_ratio.den);
1544   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)",
1545     hints.orientation, hints.forced_aspect, hints.extrasize);
1546
1547   // default video codec params
1548   am_private->gcodec.noblock     = 0;
1549   am_private->gcodec.video_pid   = am_private->video_pid;
1550   am_private->gcodec.video_type  = am_private->video_format;
1551   am_private->gcodec.stream_type = STREAM_TYPE_ES_VIDEO;
1552   am_private->gcodec.format      = am_private->video_codec_type;
1553   am_private->gcodec.width       = am_private->video_width;
1554   am_private->gcodec.height      = am_private->video_height;
1555   am_private->gcodec.rate        = am_private->video_rate;
1556   am_private->gcodec.ratio       = am_private->video_ratio;
1557   am_private->gcodec.ratio64     = am_private->video_ratio64;
1558   am_private->gcodec.param       = NULL;
1559
1560   switch(am_private->video_format)
1561   {
1562     default:
1563       break;
1564     case VFORMAT_MPEG4:
1565       am_private->gcodec.param = (void*)EXTERNAL_PTS;
1566       break;
1567     case VFORMAT_H264:
1568     case VFORMAT_H264MVC:
1569       am_private->gcodec.format = VIDEO_DEC_FORMAT_H264;
1570       am_private->gcodec.param  = (void*)EXTERNAL_PTS;
1571       // h264 in an avi file
1572       if (m_hints.ptsinvalid)
1573         am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
1574       break;
1575     case VFORMAT_REAL:
1576       am_private->stream_type = AM_STREAM_RM;
1577       am_private->vcodec.noblock = 1;
1578       am_private->vcodec.stream_type = STREAM_TYPE_RM;
1579       am_private->vcodec.am_sysinfo.ratio = 0x100;
1580       am_private->vcodec.am_sysinfo.ratio64 = 0;
1581       {
1582         static unsigned short tbl[9] = {0};
1583         if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type)
1584         {
1585           am_private->gcodec.extra = am_private->extradata[1] & 7;
1586           tbl[0] = (((am_private->gcodec.width  >> 2) - 1) << 8)
1587                  | (((am_private->gcodec.height >> 2) - 1) & 0xff);
1588           unsigned int j;
1589           for (unsigned int i = 1; i <= am_private->gcodec.extra; i++)
1590           {
1591             j = 2 * (i - 1);
1592             tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff);
1593           }
1594         }
1595         am_private->gcodec.param = &tbl;
1596       }
1597       break;
1598     case VFORMAT_VC1:
1599       // vc1 in an avi file
1600       if (m_hints.ptsinvalid)
1601         am_private->gcodec.param = (void*)EXTERNAL_PTS;
1602       break;
1603   }
1604   am_private->gcodec.param = (void *)((unsigned int)am_private->gcodec.param | (am_private->video_rotation_degree << 16));
1605
1606   // translate from generic to firemware version dependent
1607   m_dll->codec_init_para(&am_private->gcodec, &am_private->vcodec);
1608
1609   int ret = m_dll->codec_init(&am_private->vcodec);
1610   if (ret != CODEC_ERROR_NONE)
1611   {
1612     CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret);
1613     return false;
1614   }
1615   am_private->dumpdemux = false;
1616   dumpfile_open(am_private);
1617
1618   // make sure we are not stuck in pause (amcodec bug)
1619   m_dll->codec_resume(&am_private->vcodec);
1620   m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1621
1622   m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH);
1623   m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0);
1624   // disable tsync, we are playing video disconnected from audio.
1625   aml_set_sysfs_int("/sys/class/tsync/enable", 0);
1626
1627   am_private->am_pkt.codec = &am_private->vcodec;
1628   pre_header_feeding(am_private, &am_private->am_pkt);
1629
1630   Create();
1631
1632   g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1633   g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack);
1634
1635 /*
1636   // if display is set to 1080xxx, then disable deinterlacer for HD content
1637   // else bandwidth usage is too heavy and it will slow down video decoder.
1638   char display_mode[256] = {0};
1639   aml_get_sysfs_str("/sys/class/display/mode", display_mode, 255);
1640   if (strstr(display_mode,"1080"))
1641     aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 1);
1642   else
1643     aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 0);
1644 */
1645
1646   m_opened = true;
1647   // vcodec is open, update speed if it was
1648   // changed before dvdplayer called OpenDecoder.
1649   SetSpeed(m_speed);
1650
1651   return true;
1652 }
1653
1654 void CAMLCodec::CloseDecoder()
1655 {
1656   CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder");
1657   StopThread();
1658
1659   g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL);
1660   g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL);
1661
1662   // never leave vcodec ff/rw or paused.
1663   if (m_speed != DVD_PLAYSPEED_NORMAL)
1664   {
1665     m_dll->codec_resume(&am_private->vcodec);
1666     m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1667   }
1668   m_dll->codec_close(&am_private->vcodec);
1669   dumpfile_close(am_private);
1670   m_opened = false;
1671
1672   am_packet_release(&am_private->am_pkt);
1673   free(am_private->extradata);
1674   am_private->extradata = NULL;
1675   // return tsync to default so external apps work
1676   aml_set_sysfs_int("/sys/class/tsync/enable", 1);
1677
1678   ShowMainVideo(false);
1679 }
1680
1681 void CAMLCodec::Reset()
1682 {
1683   CLog::Log(LOGDEBUG, "CAMLCodec::Reset");
1684
1685   if (!m_opened)
1686     return;
1687
1688   // set the system blackout_policy to leave the last frame showing
1689   int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy");
1690   aml_set_sysfs_int("/sys/class/video/blackout_policy", 0);
1691
1692   // restore the speed (some amcodec versions require this)
1693   if (m_speed != DVD_PLAYSPEED_NORMAL)
1694   {
1695     m_dll->codec_resume(&am_private->vcodec);
1696     m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1697   }
1698   // reset the decoder
1699   m_dll->codec_reset(&am_private->vcodec);
1700   dumpfile_close(am_private);
1701   dumpfile_open(am_private);
1702
1703   // re-init our am_pkt
1704   am_packet_release(&am_private->am_pkt);
1705   am_packet_init(&am_private->am_pkt);
1706   am_private->am_pkt.codec = &am_private->vcodec;
1707   pre_header_feeding(am_private, &am_private->am_pkt);
1708
1709   // restore the saved system blackout_policy value
1710   aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy);
1711
1712   // reset some interal vars
1713   m_1st_pts = 0;
1714   m_cur_pts = 0;
1715   m_cur_pictcnt = 0;
1716   m_old_pictcnt = 0;
1717   SetSpeed(m_speed);
1718 }
1719
1720 int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
1721 {
1722   if (!m_opened)
1723     return VC_BUFFER;
1724
1725   // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during
1726   // g_renderManager.Configure call by player, which happens after the codec
1727   // OpenDecoder call. So we need to restore it but it does not seem to stick :)
1728   g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1729
1730   if (pData)
1731   {
1732     am_private->am_pkt.data = pData;
1733     am_private->am_pkt.data_size = iSize;
1734
1735     am_private->am_pkt.newflag    = 1;
1736     am_private->am_pkt.isvalid    = 1;
1737     am_private->am_pkt.avduration = 0;
1738
1739     // handle pts, including 31bit wrap, aml can only handle 31
1740     // bit pts as it uses an int in kernel.
1741     if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE)
1742       am_private->am_pkt.avpts = AV_NOPTS_VALUE;
1743     else
1744     {
1745       am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\
1746       if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff)
1747         m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff;
1748     }
1749     if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE)
1750       am_private->am_pkt.avpts -= m_start_pts;
1751
1752
1753     // handle dts, including 31bit wrap, aml can only handle 31
1754     // bit dts as it uses an int in kernel.
1755     if (dts == DVD_NOPTS_VALUE)
1756       am_private->am_pkt.avdts = AV_NOPTS_VALUE;
1757     else
1758     {
1759       am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE;
1760       if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff)
1761         m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff;
1762     }
1763     if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE)
1764       am_private->am_pkt.avdts -= m_start_dts;
1765
1766     //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)",
1767     //  iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts);
1768
1769     // some formats need header/data tweaks.
1770     // the actual write occurs once in write_av_packet
1771     // and is controlled by am_pkt.newflag.
1772     set_header_info(am_private);
1773
1774     // loop until we write all into codec, am_pkt.isvalid
1775     // will get set to zero once everything is consumed.
1776     // PLAYER_SUCCESS means all is ok, not all bytes were written.
1777     while (am_private->am_pkt.isvalid)
1778     {
1779       // abort on any errors.
1780       if (write_av_packet(am_private, &am_private->am_pkt) != PLAYER_SUCCESS)
1781         break;
1782
1783       if (am_private->am_pkt.isvalid)
1784         CLog::Log(LOGDEBUG, "CAMLCodec::Decode: write_av_packet looping");
1785     }
1786
1787     // if we seek, then GetTimeSize is wrong as
1788     // reports lastpts - cur_pts and hw decoder has
1789     // not started outputing new pts values yet.
1790     // so we grab the 1st pts sent into driver and
1791     // use that to calc GetTimeSize.
1792     if (m_1st_pts == 0)
1793       m_1st_pts = am_private->am_pkt.lastpts;
1794   }
1795
1796   // if we have still frames, demux size will be small
1797   // and we need to pre-buffer more.
1798   double target_timesize = 1.0;
1799   if (iSize < 20)
1800     target_timesize = 2.0;
1801
1802   // keep hw buffered demux above 1 second
1803   if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL)
1804     return VC_BUFFER;
1805
1806   // wait until we get a new frame or 25ms,
1807   if (m_old_pictcnt == m_cur_pictcnt)
1808     m_ready_event.WaitMSec(25);
1809
1810   // we must return VC_BUFFER or VC_PICTURE,
1811   // default to VC_BUFFER.
1812   int rtn = VC_BUFFER;
1813   if (m_old_pictcnt != m_cur_pictcnt)
1814   {
1815     m_old_pictcnt++;
1816     rtn = VC_PICTURE;
1817     // we got a new pict, try and keep hw buffered demux above 2 seconds.
1818     // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds.
1819     // we also check to make sure we keep from filling hw buffer.
1820     if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3)
1821       rtn |= VC_BUFFER;
1822   }
1823 /*
1824   CLog::Log(LOGDEBUG, "CAMLCodec::Decode: "
1825     "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)",
1826     rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize());
1827 */
1828   return rtn;
1829 }
1830
1831 bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture)
1832 {
1833   if (!m_opened)
1834     return false;
1835
1836   pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
1837   pDvdVideoPicture->format = RENDER_FMT_BYPASS;
1838   pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
1839
1840   pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
1841   pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE;
1842   // video pts cannot be late or dvdplayer goes nuts,
1843   // so run it one frame ahead
1844   pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration;
1845
1846   return true;
1847 }
1848
1849 void CAMLCodec::SetSpeed(int speed)
1850 {
1851   CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed);
1852
1853   // update internal vars regardless
1854   // of if we are open or not.
1855   m_speed = speed;
1856
1857   if (!m_opened)
1858     return;
1859
1860   switch(speed)
1861   {
1862     case DVD_PLAYSPEED_PAUSE:
1863       m_dll->codec_pause(&am_private->vcodec);
1864       m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1865       break;
1866     case DVD_PLAYSPEED_NORMAL:
1867       m_dll->codec_resume(&am_private->vcodec);
1868       m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1869       break;
1870     default:
1871       m_dll->codec_resume(&am_private->vcodec);
1872       if (am_private->video_format == VFORMAT_H264)
1873         m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB);
1874       else
1875         m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I);
1876       break;
1877   }
1878 }
1879
1880 int CAMLCodec::GetDataSize()
1881 {
1882   if (!m_opened)
1883     return 0;
1884
1885   struct buf_status vbuf ={0};
1886   if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0)
1887     m_vbufsize = vbuf.size;
1888
1889   return vbuf.data_len;
1890 }
1891
1892 double CAMLCodec::GetTimeSize()
1893 {
1894   if (!m_opened)
1895     return 0;
1896
1897   // if m_cur_pts is zero, hw decoder was not started yet
1898   // so we use the pts of the 1st demux packet that was send
1899   // to hw decoder to calc timesize.
1900   if (m_cur_pts == 0)
1901     m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ;
1902   else
1903     m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ;
1904
1905   // lie to DVDPlayer, it is hardcoded to a max of 8 seconds,
1906   // if you buffer more than 8 seconds, it goes nuts.
1907   double timesize = m_timesize;
1908   if (timesize < 0.0)
1909     timesize = 0.0;
1910   else if (timesize > 7.0)
1911     timesize = 7.0;
1912
1913   return timesize;
1914 }
1915
1916 void CAMLCodec::Process()
1917 {
1918   CLog::Log(LOGDEBUG, "CAMLCodec::Process Started");
1919
1920   // bump our priority to be level with SoftAE
1921   SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
1922   while (!m_bStop)
1923   {
1924     int64_t pts_video = 0;
1925     if (am_private->am_pkt.lastpts > 0)
1926     {
1927       // this is a blocking poll that returns every vsync.
1928       // since we are running at a higher priority, make sure
1929       // we sleep if the call fails or does a timeout.
1930       if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0)
1931       {
1932         CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed");
1933         Sleep(10);
1934       }
1935
1936       pts_video = get_pts_video();
1937       if (m_cur_pts != pts_video)
1938       {
1939         //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)",
1940         //  pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ));
1941
1942         // other threads look at these, do them first
1943         m_cur_pts = pts_video;
1944         m_cur_pictcnt++;
1945         m_ready_event.Set();
1946
1947         // correct video pts by starting pts.
1948         if (m_start_pts != 0)
1949           pts_video += m_start_pts;
1950         else if (m_start_dts != 0)
1951           pts_video += m_start_dts;
1952
1953         double app_pts = GetPlayerPtsSeconds();
1954         // add in audio delay/display latency contribution
1955         double offset  = g_renderManager.GetDisplayLatency() - CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay;
1956         // correct video pts by user set delay and rendering delay
1957         app_pts += offset;
1958
1959         //CLog::Log(LOGDEBUG, "CAMLCodec::Process: app_pts(%f), pts_video/PTS_FREQ(%f)",
1960         //  app_pts, (double)pts_video/PTS_FREQ);
1961
1962         double error = app_pts - (double)pts_video/PTS_FREQ;
1963         double abs_error = fabs(error);
1964         if (abs_error > 0.125)
1965         {
1966           //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error);
1967           if (abs_error > 0.150)
1968           {
1969             // big error so try to reset pts_pcrscr
1970             SetVideoPtsSeconds(app_pts);
1971           }
1972           else
1973           {
1974             // small error so try to avoid a frame jump
1975             SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4);
1976           }
1977         }
1978       }
1979     }
1980     else
1981     {
1982       Sleep(100);
1983     }
1984   }
1985   SetPriority(THREAD_PRIORITY_NORMAL);
1986   CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped");
1987 }
1988
1989 double CAMLCodec::GetPlayerPtsSeconds()
1990 {
1991   double clock_pts = 0.0;
1992   CDVDClock *playerclock = CDVDClock::GetMasterClock();
1993   if (playerclock)
1994     clock_pts = playerclock->GetClock() / DVD_TIME_BASE;
1995
1996   return clock_pts;
1997 }
1998
1999 void CAMLCodec::SetVideoPtsSeconds(const double pts)
2000 {
2001   //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts);
2002   if (pts >= 0.0)
2003   {
2004     int64_t pts_video = (int64_t)(pts * PTS_FREQ);
2005     if (m_start_pts != 0)
2006       pts_video -= m_start_pts;
2007     else if (m_start_dts != 0)
2008       pts_video -= m_start_dts;
2009
2010     set_pts_pcrscr(pts_video);
2011   }
2012 }
2013
2014 void CAMLCodec::ShowMainVideo(const bool show)
2015 {
2016   static int saved_disable_video = -1;
2017
2018   int disable_video = show ? 0:1;
2019   if (saved_disable_video == disable_video)
2020     return;
2021
2022   aml_set_sysfs_int("/sys/class/video/disable_video", disable_video);
2023   saved_disable_video = disable_video;
2024 }
2025
2026 void CAMLCodec::SetVideoZoom(const float zoom)
2027 {
2028   // input zoom range is 0.5 to 2.0 with a default of 1.0.
2029   // output zoom range is 2 to 300 with default of 100.
2030   // we limit that to a range of 50 to 200 with default of 100.
2031   aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom));
2032 }
2033
2034 void CAMLCodec::SetVideoContrast(const int contrast)
2035 {
2036   // input contrast range is 0 to 100 with default of 50.
2037   // output contrast range is -255 to 255 with default of 0.
2038   int aml_contrast = (255 * (contrast - 50)) / 50;
2039   aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast);
2040 }
2041 void CAMLCodec::SetVideoBrightness(const int brightness)
2042 {
2043   // input brightness range is 0 to 100 with default of 50.
2044   // output brightness range is -127 to 127 with default of 0.
2045   int aml_brightness = (127 * (brightness - 50)) / 50;
2046   aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness);
2047 }
2048 void CAMLCodec::SetVideoSaturation(const int saturation)
2049 {
2050   // output saturation range is -127 to 127 with default of 127.
2051   aml_set_sysfs_int("/sys/class/video/saturation", saturation);
2052 }
2053
2054 void CAMLCodec::GetRenderFeatures(Features &renderFeatures)
2055 {
2056   renderFeatures.push_back(RENDERFEATURE_ZOOM);
2057   renderFeatures.push_back(RENDERFEATURE_CONTRAST);
2058   renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS);
2059   renderFeatures.push_back(RENDERFEATURE_STRETCH);
2060   renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO);
2061   return;
2062 }
2063
2064 void CAMLCodec::SetVideo3dMode(const int mode3d)
2065 {
2066   aml_set_sysfs_int("/sys/class/ppmgr/ppmgr_3d_mode", mode3d);
2067 }
2068
2069 std::string CAMLCodec::GetStereoMode()
2070 {
2071   std::string  stereo_mode;
2072
2073   switch(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode)
2074   {
2075     case RENDER_STEREO_MODE_SPLIT_VERTICAL:   stereo_mode = "left_right"; break;
2076     case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: stereo_mode = "top_bottom"; break;
2077     default:                                  stereo_mode = m_hints.stereo_mode; break;
2078   }
2079
2080   if(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert)
2081     stereo_mode = RenderManager::GetStereoModeInvert(stereo_mode);
2082   return stereo_mode;
2083 }
2084
2085 void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures)
2086 {
2087   CAMLCodec *codec = (CAMLCodec*)ctx;
2088   if (codec)
2089     codec->GetRenderFeatures(renderFeatures);
2090 }
2091
2092 void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
2093 {
2094   // this routine gets called every video frame
2095   // and is in the context of the renderer thread so
2096   // do not do anything stupid here.
2097   bool update = false;
2098
2099   // video zoom adjustment.
2100   float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount;
2101   if ((int)(zoom * 1000) != (int)(m_zoom * 1000))
2102   {
2103     m_zoom = zoom;
2104   }
2105   // video contrast adjustment.
2106   int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast;
2107   if (contrast != m_contrast)
2108   {
2109     SetVideoContrast(contrast);
2110     m_contrast = contrast;
2111   }
2112   // video brightness adjustment.
2113   int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness;
2114   if (brightness != m_brightness)
2115   {
2116     SetVideoBrightness(brightness);
2117     m_brightness = brightness;
2118   }
2119
2120   // video view mode
2121   int view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
2122   if (m_view_mode != view_mode)
2123   {
2124     m_view_mode = view_mode;
2125     update = true;
2126   }
2127
2128   // video stereo mode/view.
2129   RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
2130   if (m_stereo_mode != stereo_mode)
2131   {
2132     m_stereo_mode = stereo_mode;
2133     update = true;
2134   }
2135   RENDER_STEREO_VIEW stereo_view = g_graphicsContext.GetStereoView();
2136   if (m_stereo_view != stereo_view)
2137   {
2138     // left/right/top/bottom eye,
2139     // this might change every other frame.
2140     // we do not care but just track it.
2141     m_stereo_view = stereo_view;
2142   }
2143
2144   // dest_rect
2145   if (m_dst_rect != DestRect)
2146   {
2147     m_dst_rect  = DestRect;
2148     update = true;
2149   }
2150
2151   if (!update)
2152   {
2153     // mainvideo 'should' be showing already if we get here, make sure.
2154     ShowMainVideo(true);
2155     return;
2156   }
2157
2158   CRect gui, display, dst_rect;
2159   gui = g_graphicsContext.GetViewWindow();
2160   // when display is at 1080p, we have freescale enabled
2161   // and that scales all layers into 1080p display including video,
2162   // so we have to setup video axis for 720p instead of 1080p... Boooo.
2163   display = g_graphicsContext.GetViewWindow();
2164   dst_rect = m_dst_rect;
2165   if (gui != display)
2166   {
2167     float xscale = display.Width()  / gui.Width();
2168     float yscale = display.Height() / gui.Height();
2169     dst_rect.x1 *= xscale;
2170     dst_rect.x2 *= xscale;
2171     dst_rect.y1 *= yscale;
2172     dst_rect.y2 *= yscale;
2173   }
2174
2175 #if 0
2176   std::string rectangle = StringUtils::Format("%i,%i,%i,%i",
2177     (int)dst_rect.x1, (int)dst_rect.y1,
2178     (int)dst_rect.Width(), (int)dst_rect.Height());
2179   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str());
2180   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_mode(%d)", m_stereo_mode);
2181   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_view(%d)", m_stereo_view);
2182 #endif
2183
2184   if (m_stereo_mode == RENDER_STEREO_MODE_MONO)
2185   {
2186     std::string mode = GetStereoMode();
2187     CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:mode(%s)", mode.c_str());
2188     if (mode == "left_right")
2189       SetVideo3dMode(MODE_3D_TO_2D_L);
2190     else if (mode == "right_left")
2191       SetVideo3dMode(MODE_3D_TO_2D_R);
2192     else if (mode == "top_bottom")
2193       SetVideo3dMode(MODE_3D_TO_2D_T);
2194     else if (mode == "bottom_top")
2195       SetVideo3dMode(MODE_3D_TO_2D_B);
2196     else
2197       SetVideo3dMode(MODE_3D_DISABLE);
2198   }
2199   else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
2200   {
2201     dst_rect.x2 *= 2.0;
2202     //SetVideo3dMode(MODE_3D_LR);
2203     SetVideo3dMode(MODE_3D_DISABLE);
2204   }
2205   else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
2206   {
2207     dst_rect.y2 *= 2.0;
2208     //SetVideo3dMode(MODE_3D_BT);
2209     SetVideo3dMode(MODE_3D_DISABLE);
2210   }
2211   else
2212   {
2213     SetVideo3dMode(MODE_3D_DISABLE);
2214   }
2215
2216   // goofy 0/1 based difference in aml axis coordinates.
2217   // fix them.
2218   dst_rect.x2--;
2219   dst_rect.y2--;
2220
2221   char video_axis[256] = {};
2222   sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2);
2223
2224   aml_set_sysfs_str("/sys/class/video/axis", video_axis);
2225   // make sure we are in 'full stretch' so we can stretch
2226   aml_set_sysfs_int("/sys/class/video/screen_mode", 1);
2227
2228   // we only get called once gui has changed to something
2229   // that would show video playback, so show it.
2230   ShowMainVideo(true);
2231 }
2232
2233 void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
2234 {
2235   CAMLCodec *codec = (CAMLCodec*)ctx;
2236   codec->SetVideoRect(SrcRect, DestRect);
2237 }