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