3a5cc9762904a6846d4f3cadced9dcd7b0b394a7
[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_H264_4K2K == 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   if (am_private->video_format == VFORMAT_H264) {
1516       if (hints.width > 1920 || hints.height > 1088) {
1517         am_private->video_format = VFORMAT_H264_4K2K;
1518       }
1519   }
1520   switch (am_private->video_format)
1521   {
1522     default:
1523       am_private->extrasize       = hints.extrasize;
1524       am_private->extradata       = (uint8_t*)malloc(hints.extrasize);
1525       memcpy(am_private->extradata, hints.extradata, hints.extrasize);
1526       break;
1527     case VFORMAT_REAL:
1528     case VFORMAT_MPEG12:
1529       break;
1530   }
1531
1532   if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0)
1533     am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag);
1534   else
1535     am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id);
1536
1537   am_private->flv_flag = 0;
1538   if (am_private->video_codec_id == AV_CODEC_ID_FLV1)
1539   {
1540     am_private->video_codec_tag = CODEC_TAG_F263;
1541     am_private->flv_flag = 1;
1542   }
1543
1544   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder "
1545     "hints.width(%d), hints.height(%d), hints.codec(%d), hints.codec_tag(%d), hints.pid(%d)",
1546     hints.width, hints.height, hints.codec, hints.codec_tag, hints.pid);
1547   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)",
1548     hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate);
1549   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)",
1550     hints.aspect, video_ratio.num, video_ratio.den);
1551   CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)",
1552     hints.orientation, hints.forced_aspect, hints.extrasize);
1553
1554   // default video codec params
1555   am_private->gcodec.noblock     = 0;
1556   am_private->gcodec.video_pid   = am_private->video_pid;
1557   am_private->gcodec.video_type  = am_private->video_format;
1558   am_private->gcodec.stream_type = STREAM_TYPE_ES_VIDEO;
1559   am_private->gcodec.format      = am_private->video_codec_type;
1560   am_private->gcodec.width       = am_private->video_width;
1561   am_private->gcodec.height      = am_private->video_height;
1562   am_private->gcodec.rate        = am_private->video_rate;
1563   am_private->gcodec.ratio       = am_private->video_ratio;
1564   am_private->gcodec.ratio64     = am_private->video_ratio64;
1565   am_private->gcodec.param       = NULL;
1566
1567   switch(am_private->video_format)
1568   {
1569     default:
1570       break;
1571     case VFORMAT_MPEG4:
1572       am_private->gcodec.param = (void*)EXTERNAL_PTS;
1573       break;
1574     case VFORMAT_H264:
1575     case VFORMAT_H264MVC:
1576       am_private->gcodec.format = VIDEO_DEC_FORMAT_H264;
1577       am_private->gcodec.param  = (void*)EXTERNAL_PTS;
1578       // h264 in an avi file
1579       if (m_hints.ptsinvalid)
1580         am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
1581       break;
1582     case VFORMAT_H264_4K2K:
1583       if (aml_get_cputype() >= 8) {
1584         am_private->gcodec.format = VIDEO_DEC_FORMAT_H264_4K2K;
1585         am_private->gcodec.param  = (void*)EXTERNAL_PTS;
1586         // h264 in an avi file
1587         if (m_hints.ptsinvalid)
1588           am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
1589       } else {
1590         CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, 4K supported only on Meson8.");
1591         return false;
1592       }
1593       break; 
1594     case VFORMAT_REAL:
1595       am_private->stream_type = AM_STREAM_RM;
1596       am_private->vcodec.noblock = 1;
1597       am_private->vcodec.stream_type = STREAM_TYPE_RM;
1598       am_private->vcodec.am_sysinfo.ratio = 0x100;
1599       am_private->vcodec.am_sysinfo.ratio64 = 0;
1600       {
1601         static unsigned short tbl[9] = {0};
1602         if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type)
1603         {
1604           am_private->gcodec.extra = am_private->extradata[1] & 7;
1605           tbl[0] = (((am_private->gcodec.width  >> 2) - 1) << 8)
1606                  | (((am_private->gcodec.height >> 2) - 1) & 0xff);
1607           unsigned int j;
1608           for (unsigned int i = 1; i <= am_private->gcodec.extra; i++)
1609           {
1610             j = 2 * (i - 1);
1611             tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff);
1612           }
1613         }
1614         am_private->gcodec.param = &tbl;
1615       }
1616       break;
1617     case VFORMAT_VC1:
1618       // vc1 in an avi file
1619       if (m_hints.ptsinvalid)
1620         am_private->gcodec.param = (void*)EXTERNAL_PTS;
1621       break;
1622   }
1623   am_private->gcodec.param = (void *)((unsigned int)am_private->gcodec.param | (am_private->video_rotation_degree << 16));
1624
1625   // translate from generic to firemware version dependent
1626   m_dll->codec_init_para(&am_private->gcodec, &am_private->vcodec);
1627
1628   int ret = m_dll->codec_init(&am_private->vcodec);
1629   if (ret != CODEC_ERROR_NONE)
1630   {
1631     CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret);
1632     return false;
1633   }
1634
1635   am_private->dumpdemux = false;
1636   dumpfile_open(am_private);
1637
1638   // make sure we are not stuck in pause (amcodec bug)
1639   m_dll->codec_resume(&am_private->vcodec);
1640   m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1641
1642   m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH);
1643   m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0);
1644   // disable tsync, we are playing video disconnected from audio.
1645   aml_set_sysfs_int("/sys/class/tsync/enable", 0);
1646
1647   am_private->am_pkt.codec = &am_private->vcodec;
1648   pre_header_feeding(am_private, &am_private->am_pkt);
1649
1650   Create();
1651
1652   g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1653   g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack);
1654
1655 /*
1656   // if display is set to 1080xxx, then disable deinterlacer for HD content
1657   // else bandwidth usage is too heavy and it will slow down video decoder.
1658   char display_mode[256] = {0};
1659   aml_get_sysfs_str("/sys/class/display/mode", display_mode, 255);
1660   if (strstr(display_mode,"1080"))
1661     aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 1);
1662   else
1663     aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 0);
1664 */
1665
1666   m_opened = true;
1667   // vcodec is open, update speed if it was
1668   // changed before dvdplayer called OpenDecoder.
1669   SetSpeed(m_speed);
1670
1671   return true;
1672 }
1673
1674 void CAMLCodec::CloseDecoder()
1675 {
1676   CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder");
1677   StopThread();
1678
1679   g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL);
1680   g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL);
1681
1682   // never leave vcodec ff/rw or paused.
1683   if (m_speed != DVD_PLAYSPEED_NORMAL)
1684   {
1685     m_dll->codec_resume(&am_private->vcodec);
1686     m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1687   }
1688   m_dll->codec_close(&am_private->vcodec);
1689   dumpfile_close(am_private);
1690   m_opened = false;
1691
1692   am_packet_release(&am_private->am_pkt);
1693   free(am_private->extradata);
1694   am_private->extradata = NULL;
1695   // return tsync to default so external apps work
1696   aml_set_sysfs_int("/sys/class/tsync/enable", 1);
1697
1698   ShowMainVideo(false);
1699 }
1700
1701 void CAMLCodec::Reset()
1702 {
1703   CLog::Log(LOGDEBUG, "CAMLCodec::Reset");
1704
1705   if (!m_opened)
1706     return;
1707
1708   // set the system blackout_policy to leave the last frame showing
1709   int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy");
1710   aml_set_sysfs_int("/sys/class/video/blackout_policy", 0);
1711
1712   // restore the speed (some amcodec versions require this)
1713   if (m_speed != DVD_PLAYSPEED_NORMAL)
1714   {
1715     m_dll->codec_resume(&am_private->vcodec);
1716     m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1717   }
1718   // reset the decoder
1719   m_dll->codec_reset(&am_private->vcodec);
1720   dumpfile_close(am_private);
1721   dumpfile_open(am_private);
1722
1723   // re-init our am_pkt
1724   am_packet_release(&am_private->am_pkt);
1725   am_packet_init(&am_private->am_pkt);
1726   am_private->am_pkt.codec = &am_private->vcodec;
1727   pre_header_feeding(am_private, &am_private->am_pkt);
1728
1729   // restore the saved system blackout_policy value
1730   aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy);
1731
1732   // reset some interal vars
1733   m_1st_pts = 0;
1734   m_cur_pts = 0;
1735   m_cur_pictcnt = 0;
1736   m_old_pictcnt = 0;
1737   SetSpeed(m_speed);
1738 }
1739
1740 int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
1741 {
1742   if (!m_opened)
1743     return VC_BUFFER;
1744
1745   // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during
1746   // g_renderManager.Configure call by player, which happens after the codec
1747   // OpenDecoder call. So we need to restore it but it does not seem to stick :)
1748   g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1749
1750   if (pData)
1751   {
1752     am_private->am_pkt.data = pData;
1753     am_private->am_pkt.data_size = iSize;
1754
1755     am_private->am_pkt.newflag    = 1;
1756     am_private->am_pkt.isvalid    = 1;
1757     am_private->am_pkt.avduration = 0;
1758
1759     // handle pts, including 31bit wrap, aml can only handle 31
1760     // bit pts as it uses an int in kernel.
1761     if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE)
1762       am_private->am_pkt.avpts = AV_NOPTS_VALUE;
1763     else
1764     {
1765       am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\
1766       if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff)
1767         m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff;
1768     }
1769     if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE)
1770       am_private->am_pkt.avpts -= m_start_pts;
1771
1772
1773     // handle dts, including 31bit wrap, aml can only handle 31
1774     // bit dts as it uses an int in kernel.
1775     if (dts == DVD_NOPTS_VALUE)
1776       am_private->am_pkt.avdts = AV_NOPTS_VALUE;
1777     else
1778     {
1779       am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE;
1780       if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff)
1781         m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff;
1782     }
1783     if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE)
1784       am_private->am_pkt.avdts -= m_start_dts;
1785
1786     //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)",
1787     //  iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts);
1788
1789     // some formats need header/data tweaks.
1790     // the actual write occurs once in write_av_packet
1791     // and is controlled by am_pkt.newflag.
1792     set_header_info(am_private);
1793
1794     // loop until we write all into codec, am_pkt.isvalid
1795     // will get set to zero once everything is consumed.
1796     // PLAYER_SUCCESS means all is ok, not all bytes were written.
1797     while (am_private->am_pkt.isvalid)
1798     {
1799       // abort on any errors.
1800       if (write_av_packet(am_private, &am_private->am_pkt) != PLAYER_SUCCESS)
1801         break;
1802
1803       if (am_private->am_pkt.isvalid)
1804         CLog::Log(LOGDEBUG, "CAMLCodec::Decode: write_av_packet looping");
1805     }
1806
1807     // if we seek, then GetTimeSize is wrong as
1808     // reports lastpts - cur_pts and hw decoder has
1809     // not started outputing new pts values yet.
1810     // so we grab the 1st pts sent into driver and
1811     // use that to calc GetTimeSize.
1812     if (m_1st_pts == 0)
1813       m_1st_pts = am_private->am_pkt.lastpts;
1814   }
1815
1816   // if we have still frames, demux size will be small
1817   // and we need to pre-buffer more.
1818   double target_timesize = 1.0;
1819   if (iSize < 20)
1820     target_timesize = 2.0;
1821
1822   // keep hw buffered demux above 1 second
1823   if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL)
1824     return VC_BUFFER;
1825
1826   // wait until we get a new frame or 25ms,
1827   if (m_old_pictcnt == m_cur_pictcnt)
1828     m_ready_event.WaitMSec(25);
1829
1830   // we must return VC_BUFFER or VC_PICTURE,
1831   // default to VC_BUFFER.
1832   int rtn = VC_BUFFER;
1833   if (m_old_pictcnt != m_cur_pictcnt)
1834   {
1835     m_old_pictcnt++;
1836     rtn = VC_PICTURE;
1837     // we got a new pict, try and keep hw buffered demux above 2 seconds.
1838     // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds.
1839     // we also check to make sure we keep from filling hw buffer.
1840     if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3)
1841       rtn |= VC_BUFFER;
1842   }
1843 /*
1844   CLog::Log(LOGDEBUG, "CAMLCodec::Decode: "
1845     "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)",
1846     rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize());
1847 */
1848   return rtn;
1849 }
1850
1851 bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture)
1852 {
1853   if (!m_opened)
1854     return false;
1855
1856   pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
1857   pDvdVideoPicture->format = RENDER_FMT_BYPASS;
1858   pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
1859
1860   pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
1861   if (m_speed == DVD_PLAYSPEED_NORMAL)
1862   {
1863     pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE;
1864     // video pts cannot be late or dvdplayer goes nuts,
1865     // so run it one frame ahead
1866     pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration;
1867   }
1868   else
1869   {
1870     // We are FF/RW; Do not use the Player clock or it just doesn't work
1871     if (m_cur_pts == 0)
1872       pDvdVideoPicture->pts = (double)m_1st_pts / PTS_FREQ * DVD_TIME_BASE;
1873     else
1874       pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE;
1875   }
1876
1877   return true;
1878 }
1879
1880 void CAMLCodec::SetSpeed(int speed)
1881 {
1882   CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed);
1883
1884   // update internal vars regardless
1885   // of if we are open or not.
1886   m_speed = speed;
1887
1888   if (!m_opened)
1889     return;
1890
1891   switch(speed)
1892   {
1893     case DVD_PLAYSPEED_PAUSE:
1894       m_dll->codec_pause(&am_private->vcodec);
1895       m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1896       break;
1897     case DVD_PLAYSPEED_NORMAL:
1898       m_dll->codec_resume(&am_private->vcodec);
1899       m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1900       break;
1901     default:
1902       m_dll->codec_resume(&am_private->vcodec);
1903       if ((am_private->video_format == VFORMAT_H264) || (am_private->video_format == VFORMAT_H264_4K2K))
1904         m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB);
1905       else
1906         m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I);
1907       break;
1908   }
1909 }
1910
1911 int CAMLCodec::GetDataSize()
1912 {
1913   if (!m_opened)
1914     return 0;
1915
1916   struct buf_status vbuf ={0};
1917   if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0)
1918     m_vbufsize = vbuf.size;
1919
1920   return vbuf.data_len;
1921 }
1922
1923 double CAMLCodec::GetTimeSize()
1924 {
1925   if (!m_opened)
1926     return 0;
1927
1928   // if m_cur_pts is zero, hw decoder was not started yet
1929   // so we use the pts of the 1st demux packet that was send
1930   // to hw decoder to calc timesize.
1931   if (m_cur_pts == 0)
1932     m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ;
1933   else
1934     m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ;
1935
1936   // lie to DVDPlayer, it is hardcoded to a max of 8 seconds,
1937   // if you buffer more than 8 seconds, it goes nuts.
1938   double timesize = m_timesize;
1939   if (timesize < 0.0)
1940     timesize = 0.0;
1941   else if (timesize > 7.0)
1942     timesize = 7.0;
1943
1944   return timesize;
1945 }
1946
1947 void CAMLCodec::Process()
1948 {
1949   CLog::Log(LOGDEBUG, "CAMLCodec::Process Started");
1950
1951   // bump our priority to be level with SoftAE
1952   SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
1953   while (!m_bStop)
1954   {
1955     int64_t pts_video = 0;
1956     if (am_private->am_pkt.lastpts > 0)
1957     {
1958       // this is a blocking poll that returns every vsync.
1959       // since we are running at a higher priority, make sure
1960       // we sleep if the call fails or does a timeout.
1961       if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0)
1962       {
1963         CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed");
1964         Sleep(10);
1965       }
1966
1967       pts_video = get_pts_video();
1968       if (m_cur_pts != pts_video)
1969       {
1970         //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)",
1971         //  pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ));
1972
1973         // other threads look at these, do them first
1974         m_cur_pts = pts_video;
1975         m_cur_pictcnt++;
1976         m_ready_event.Set();
1977
1978         // correct video pts by starting pts.
1979         if (m_start_pts != 0)
1980           pts_video += m_start_pts;
1981         else if (m_start_dts != 0)
1982           pts_video += m_start_dts;
1983
1984         double app_pts = GetPlayerPtsSeconds();
1985         // add in audio delay/display latency contribution
1986         double offset  = g_renderManager.GetDisplayLatency() - CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay;
1987         // correct video pts by user set delay and rendering delay
1988         app_pts += offset;
1989
1990         //CLog::Log(LOGDEBUG, "CAMLCodec::Process: app_pts(%f), pts_video/PTS_FREQ(%f)",
1991         //  app_pts, (double)pts_video/PTS_FREQ);
1992
1993         double error = app_pts - (double)pts_video/PTS_FREQ;
1994         double abs_error = fabs(error);
1995         if (abs_error > 0.125)
1996         {
1997           //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error);
1998           if (abs_error > 0.150)
1999           {
2000             // big error so try to reset pts_pcrscr
2001             SetVideoPtsSeconds(app_pts);
2002           }
2003           else
2004           {
2005             // small error so try to avoid a frame jump
2006             SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4);
2007           }
2008         }
2009       }
2010     }
2011     else
2012     {
2013       Sleep(100);
2014     }
2015   }
2016   SetPriority(THREAD_PRIORITY_NORMAL);
2017   CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped");
2018 }
2019
2020 double CAMLCodec::GetPlayerPtsSeconds()
2021 {
2022   double clock_pts = 0.0;
2023   CDVDClock *playerclock = CDVDClock::GetMasterClock();
2024   if (playerclock)
2025     clock_pts = playerclock->GetClock() / DVD_TIME_BASE;
2026
2027   return clock_pts;
2028 }
2029
2030 void CAMLCodec::SetVideoPtsSeconds(const double pts)
2031 {
2032   //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts);
2033   if (pts >= 0.0)
2034   {
2035     int64_t pts_video = (int64_t)(pts * PTS_FREQ);
2036     if (m_start_pts != 0)
2037       pts_video -= m_start_pts;
2038     else if (m_start_dts != 0)
2039       pts_video -= m_start_dts;
2040
2041     set_pts_pcrscr(pts_video);
2042   }
2043 }
2044
2045 void CAMLCodec::ShowMainVideo(const bool show)
2046 {
2047   static int saved_disable_video = -1;
2048
2049   int disable_video = show ? 0:1;
2050   if (saved_disable_video == disable_video)
2051     return;
2052
2053   aml_set_sysfs_int("/sys/class/video/disable_video", disable_video);
2054   saved_disable_video = disable_video;
2055 }
2056
2057 void CAMLCodec::SetVideoZoom(const float zoom)
2058 {
2059   // input zoom range is 0.5 to 2.0 with a default of 1.0.
2060   // output zoom range is 2 to 300 with default of 100.
2061   // we limit that to a range of 50 to 200 with default of 100.
2062   aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom));
2063 }
2064
2065 void CAMLCodec::SetVideoContrast(const int contrast)
2066 {
2067   // input contrast range is 0 to 100 with default of 50.
2068   // output contrast range is -255 to 255 with default of 0.
2069   int aml_contrast = (255 * (contrast - 50)) / 50;
2070   aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast);
2071 }
2072 void CAMLCodec::SetVideoBrightness(const int brightness)
2073 {
2074   // input brightness range is 0 to 100 with default of 50.
2075   // output brightness range is -127 to 127 with default of 0.
2076   int aml_brightness = (127 * (brightness - 50)) / 50;
2077   aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness);
2078 }
2079 void CAMLCodec::SetVideoSaturation(const int saturation)
2080 {
2081   // output saturation range is -127 to 127 with default of 127.
2082   aml_set_sysfs_int("/sys/class/video/saturation", saturation);
2083 }
2084
2085 void CAMLCodec::GetRenderFeatures(Features &renderFeatures)
2086 {
2087   renderFeatures.push_back(RENDERFEATURE_ZOOM);
2088   renderFeatures.push_back(RENDERFEATURE_CONTRAST);
2089   renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS);
2090   renderFeatures.push_back(RENDERFEATURE_STRETCH);
2091   renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO);
2092   return;
2093 }
2094
2095 void CAMLCodec::SetVideo3dMode(const int mode3d)
2096 {
2097   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideo3dMode:mode3d(0x%x)", mode3d);
2098   aml_set_sysfs_int("/sys/class/ppmgr/ppmgr_3d_mode", mode3d);
2099 }
2100
2101 std::string CAMLCodec::GetStereoMode()
2102 {
2103   std::string  stereo_mode;
2104
2105   switch(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode)
2106   {
2107     case RENDER_STEREO_MODE_SPLIT_VERTICAL:   stereo_mode = "left_right"; break;
2108     case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: stereo_mode = "top_bottom"; break;
2109     default:                                  stereo_mode = m_hints.stereo_mode; break;
2110   }
2111
2112   if(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert)
2113     stereo_mode = RenderManager::GetStereoModeInvert(stereo_mode);
2114   return stereo_mode;
2115 }
2116
2117 void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures)
2118 {
2119   CAMLCodec *codec = (CAMLCodec*)ctx;
2120   if (codec)
2121     codec->GetRenderFeatures(renderFeatures);
2122 }
2123
2124 void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
2125 {
2126   // this routine gets called every video frame
2127   // and is in the context of the renderer thread so
2128   // do not do anything stupid here.
2129   bool update = false;
2130
2131   // video zoom adjustment.
2132   float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount;
2133   if ((int)(zoom * 1000) != (int)(m_zoom * 1000))
2134   {
2135     m_zoom = zoom;
2136   }
2137   // video contrast adjustment.
2138   int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast;
2139   if (contrast != m_contrast)
2140   {
2141     SetVideoContrast(contrast);
2142     m_contrast = contrast;
2143   }
2144   // video brightness adjustment.
2145   int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness;
2146   if (brightness != m_brightness)
2147   {
2148     SetVideoBrightness(brightness);
2149     m_brightness = brightness;
2150   }
2151
2152   // video view mode
2153   int view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
2154   if (m_view_mode != view_mode)
2155   {
2156     m_view_mode = view_mode;
2157     update = true;
2158   }
2159
2160   // video stereo mode/view.
2161   RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
2162   if (m_stereo_mode != stereo_mode)
2163   {
2164     m_stereo_mode = stereo_mode;
2165     update = true;
2166   }
2167   RENDER_STEREO_VIEW stereo_view = g_graphicsContext.GetStereoView();
2168   if (m_stereo_view != stereo_view)
2169   {
2170     // left/right/top/bottom eye,
2171     // this might change every other frame.
2172     // we do not care but just track it.
2173     m_stereo_view = stereo_view;
2174   }
2175
2176   // dest_rect
2177   if (m_dst_rect != DestRect)
2178   {
2179     m_dst_rect  = DestRect;
2180     update = true;
2181   }
2182
2183   if (!update)
2184   {
2185     // mainvideo 'should' be showing already if we get here, make sure.
2186     ShowMainVideo(true);
2187     return;
2188   }
2189
2190   CRect gui, display, dst_rect;
2191   gui = g_graphicsContext.GetViewWindow();
2192   // when display is at 1080p, we have freescale enabled
2193   // and that scales all layers into 1080p display including video,
2194   // so we have to setup video axis for 720p instead of 1080p... Boooo.
2195   display = g_graphicsContext.GetViewWindow();
2196   dst_rect = m_dst_rect;
2197   if (gui != display)
2198   {
2199     float xscale = display.Width()  / gui.Width();
2200     float yscale = display.Height() / gui.Height();
2201     dst_rect.x1 *= xscale;
2202     dst_rect.x2 *= xscale;
2203     dst_rect.y1 *= yscale;
2204     dst_rect.y2 *= yscale;
2205   }
2206
2207 #if 0
2208   std::string rectangle = StringUtils::Format("%i,%i,%i,%i",
2209     (int)dst_rect.x1, (int)dst_rect.y1,
2210     (int)dst_rect.Width(), (int)dst_rect.Height());
2211   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str());
2212   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_mode(%d)", m_stereo_mode);
2213   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_view(%d)", m_stereo_view);
2214 #endif
2215
2216   if (m_stereo_mode == RENDER_STEREO_MODE_MONO)
2217   {
2218     std::string mode = GetStereoMode();
2219     if (mode == "left_right")
2220       SetVideo3dMode(MODE_3D_TO_2D_L);
2221     else if (mode == "right_left")
2222       SetVideo3dMode(MODE_3D_TO_2D_R);
2223     else if (mode == "top_bottom")
2224       SetVideo3dMode(MODE_3D_TO_2D_T);
2225     else if (mode == "bottom_top")
2226       SetVideo3dMode(MODE_3D_TO_2D_B);
2227     else
2228       SetVideo3dMode(MODE_3D_DISABLE);
2229   }
2230   else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
2231   {
2232     dst_rect.x2 *= 2.0;
2233     SetVideo3dMode(MODE_3D_DISABLE);
2234   }
2235   else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
2236   {
2237     dst_rect.y2 *= 2.0;
2238     SetVideo3dMode(MODE_3D_DISABLE);
2239   }
2240   else if (m_stereo_mode == RENDER_STEREO_MODE_INTERLACED)
2241   {
2242     std::string mode = GetStereoMode();
2243     if (mode == "left_right")
2244       SetVideo3dMode(MODE_3D_LR);
2245     else if (mode == "right_left")
2246       SetVideo3dMode(MODE_3D_LR_SWITCH);
2247     else if (mode == "row_interleaved_lr")
2248       SetVideo3dMode(MODE_3D_LR);
2249     else if (mode == "row_interleaved_rl")
2250       SetVideo3dMode(MODE_3D_LR_SWITCH);
2251     else
2252       SetVideo3dMode(MODE_3D_DISABLE);
2253   }
2254   else
2255   {
2256     SetVideo3dMode(MODE_3D_DISABLE);
2257   }
2258
2259   // goofy 0/1 based difference in aml axis coordinates.
2260   // fix them.
2261   dst_rect.x2--;
2262   dst_rect.y2--;
2263
2264   char video_axis[256] = {};
2265   sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2);
2266
2267   aml_set_sysfs_str("/sys/class/video/axis", video_axis);
2268   // make sure we are in 'full stretch' so we can stretch
2269   aml_set_sysfs_int("/sys/class/video/screen_mode", 1);
2270
2271   // we only get called once gui has changed to something
2272   // that would show video playback, so show it.
2273   ShowMainVideo(true);
2274 }
2275
2276 void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
2277 {
2278   CAMLCodec *codec = (CAMLCodec*)ctx;
2279   codec->SetVideoRect(SrcRect, DestRect);
2280 }