2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
24 #include "DynamicDll.h"
26 #include "cores/dvdplayer/DVDClock.h"
27 #include "cores/VideoRenderers/RenderManager.h"
28 #include "guilib/GraphicContext.h"
29 #include "settings/MediaSettings.h"
30 #include "settings/Settings.h"
31 #include "utils/AMLUtils.h"
32 #include "utils/log.h"
33 #include "utils/TimeUtils.h"
39 #include <semaphore.h>
43 #include <sys/ioctl.h>
47 #include <amcodec/codec.h>
50 class DllLibamCodecInterface
53 virtual ~DllLibamCodecInterface() {};
55 virtual int codec_init(codec_para_t *pcodec)=0;
56 virtual int codec_close(codec_para_t *pcodec)=0;
57 virtual int codec_reset(codec_para_t *pcodec)=0;
58 virtual int codec_pause(codec_para_t *pcodec)=0;
59 virtual int codec_resume(codec_para_t *pcodec)=0;
60 virtual int codec_write(codec_para_t *pcodec, void *buffer, int len)=0;
61 virtual int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts)=0;
62 virtual int codec_get_vbuf_state(codec_para_t *pcodec, struct buf_status *buf)=0;
63 virtual int codec_get_vdec_state(codec_para_t *pcodec, struct vdec_status *vdec)=0;
65 virtual int codec_init_cntl(codec_para_t *pcodec)=0;
66 virtual int codec_poll_cntl(codec_para_t *pcodec)=0;
67 virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0;
68 virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int avthresh)=0;
69 virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0;
71 // grab these from libamplayer
72 virtual int h263vld(unsigned char *inbuf, unsigned char *outbuf, int inbuf_len, int s263)=0;
73 virtual int decodeble_h263(unsigned char *buf)=0;
75 // grab this from amffmpeg so we do not have to load DllAvUtil
76 virtual AVRational av_d2q(double d, int max)=0;
79 class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
81 // libamcodec is static linked into libamplayer.so
82 DECLARE_DLL_WRAPPER(DllLibAmCodec, "libamplayer.so")
84 DEFINE_METHOD1(int, codec_init, (codec_para_t *p1))
85 DEFINE_METHOD1(int, codec_close, (codec_para_t *p1))
86 DEFINE_METHOD1(int, codec_reset, (codec_para_t *p1))
87 DEFINE_METHOD1(int, codec_pause, (codec_para_t *p1))
88 DEFINE_METHOD1(int, codec_resume, (codec_para_t *p1))
89 DEFINE_METHOD3(int, codec_write, (codec_para_t *p1, void *p2, int p3))
90 DEFINE_METHOD2(int, codec_checkin_pts, (codec_para_t *p1, unsigned long p2))
91 DEFINE_METHOD2(int, codec_get_vbuf_state, (codec_para_t *p1, struct buf_status * p2))
92 DEFINE_METHOD2(int, codec_get_vdec_state, (codec_para_t *p1, struct vdec_status * p2))
94 DEFINE_METHOD1(int, codec_init_cntl, (codec_para_t *p1))
95 DEFINE_METHOD1(int, codec_poll_cntl, (codec_para_t *p1))
96 DEFINE_METHOD2(int, codec_set_cntl_mode, (codec_para_t *p1, unsigned int p2))
97 DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2))
98 DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2))
100 DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4))
101 DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1))
103 DEFINE_METHOD2(AVRational, av_d2q, (double p1, int p2))
105 BEGIN_METHOD_RESOLVE()
106 RESOLVE_METHOD(codec_init)
107 RESOLVE_METHOD(codec_close)
108 RESOLVE_METHOD(codec_reset)
109 RESOLVE_METHOD(codec_pause)
110 RESOLVE_METHOD(codec_resume)
111 RESOLVE_METHOD(codec_write)
112 RESOLVE_METHOD(codec_checkin_pts)
113 RESOLVE_METHOD(codec_get_vbuf_state)
114 RESOLVE_METHOD(codec_get_vdec_state)
116 RESOLVE_METHOD(codec_init_cntl)
117 RESOLVE_METHOD(codec_poll_cntl)
118 RESOLVE_METHOD(codec_set_cntl_mode)
119 RESOLVE_METHOD(codec_set_cntl_avthresh)
120 RESOLVE_METHOD(codec_set_cntl_syncthresh)
122 RESOLVE_METHOD(h263vld)
123 RESOLVE_METHOD(decodeble_h263)
125 RESOLVE_METHOD(av_d2q)
129 //-----------------------------------------------------------------------------------
130 //-----------------------------------------------------------------------------------
131 // AppContext - Application state
132 #define PTS_FREQ 90000
133 #define UNIT_FREQ 96000
134 #define AV_SYNC_THRESH PTS_FREQ*30
136 #define TRICKMODE_NONE 0x00
137 #define TRICKMODE_I 0x01
138 #define TRICKMODE_FFFB 0x02
140 // same as AV_NOPTS_VALUE
141 #define INT64_0 INT64_C(0x8000000000000000)
143 #define EXTERNAL_PTS (1)
144 #define SYNC_OUTSIDE (2)
147 #define CODEC_TAG_VC_1 (0x312D4356)
148 #define CODEC_TAG_RV30 (0x30335652)
149 #define CODEC_TAG_RV40 (0x30345652)
150 #define CODEC_TAG_MJPEG (0x47504a4d)
151 #define CODEC_TAG_mjpeg (0x47504a4c)
152 #define CODEC_TAG_jpeg (0x6765706a)
153 #define CODEC_TAG_mjpa (0x61706a6d)
155 #define RW_WAIT_TIME (20 * 1000) // 20ms
157 #define P_PRE (0x02000000)
158 #define F_PRE (0x03000000)
159 #define PLAYER_SUCCESS (0)
160 #define PLAYER_FAILED (-(P_PRE|0x01))
161 #define PLAYER_NOMEM (-(P_PRE|0x02))
162 #define PLAYER_EMPTY_P (-(P_PRE|0x03))
164 #define PLAYER_WR_FAILED (-(P_PRE|0x21))
165 #define PLAYER_WR_EMPTYP (-(P_PRE|0x22))
166 #define PLAYER_WR_FINISH (P_PRE|0x1)
168 #define PLAYER_PTS_ERROR (-(P_PRE|0x31))
169 #define PLAYER_UNSUPPORT (-(P_PRE|0x35))
170 #define PLAYER_CHECK_CODEC_ERROR (-(P_PRE|0x39))
172 #define HDR_BUF_SIZE 1024
173 typedef struct hdr_buf {
178 typedef struct am_packet {
195 AM_STREAM_UNKNOWN = 0,
204 typedef struct am_private_t
209 pstream_type stream_type;
212 vformat_t video_format;
214 unsigned int video_codec_id;
215 unsigned int video_codec_tag;
216 vdec_type_t video_codec_type;
217 unsigned int video_width;
218 unsigned int video_height;
219 unsigned int video_ratio;
220 unsigned int video_ratio64;
221 unsigned int video_rate;
222 unsigned int video_rotation_degree;
227 DllLibAmCodec *m_dll;
233 /*************************************************************************/
234 /*************************************************************************/
235 void dumpfile_open(am_private_t *para)
239 static int amcodec_dumpid = 0;
240 char dump_path[128] = {0};
241 sprintf(dump_path, "/temp/dump_amcodec-%d.dat", amcodec_dumpid++);
243 para->dumpfile = open(dump_path, O_CREAT | O_RDWR, 0666);
246 void dumpfile_close(am_private_t *para)
248 if (para->dumpdemux && para->dumpfile != -1)
249 close(para->dumpfile), para->dumpfile = -1;
251 void dumpfile_write(am_private_t *para, void* buf, int bufsiz)
255 CLog::Log(LOGERROR, "dumpfile_write: wtf ? buf is null, bufsiz(%d)", bufsiz);
259 if (para->dumpdemux && para->dumpfile != -1)
260 write(para->dumpfile, buf, bufsiz);
263 /*************************************************************************/
264 /*************************************************************************/
265 static int64_t get_pts_video()
267 int fd = open("/sys/class/tsync/pts_video", O_RDONLY);
271 int size = read(fd, pts_str, sizeof(pts_str));
275 unsigned long pts = strtoul(pts_str, NULL, 16);
280 CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error");
284 static int set_pts_pcrscr(int64_t value)
286 int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY);
290 unsigned long pts = (unsigned long)value;
291 sprintf(pts_str, "0x%lx", pts);
292 write(fd, pts_str, strlen(pts_str));
297 CLog::Log(LOGERROR, "set_pts_pcrscr: open pts_pcrscr error");
301 static vformat_t codecid_to_vformat(enum AVCodecID id)
306 case AV_CODEC_ID_MPEG1VIDEO:
307 case AV_CODEC_ID_MPEG2VIDEO:
308 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
309 format = VFORMAT_MPEG12;
311 case AV_CODEC_ID_H263:
312 case AV_CODEC_ID_MPEG4:
313 case AV_CODEC_ID_H263P:
314 case AV_CODEC_ID_H263I:
315 case AV_CODEC_ID_MSMPEG4V2:
316 case AV_CODEC_ID_MSMPEG4V3:
317 case AV_CODEC_ID_FLV1:
318 format = VFORMAT_MPEG4;
320 case AV_CODEC_ID_RV10:
321 case AV_CODEC_ID_RV20:
322 case AV_CODEC_ID_RV30:
323 case AV_CODEC_ID_RV40:
324 format = VFORMAT_REAL;
326 case AV_CODEC_ID_H264:
327 format = VFORMAT_H264;
330 case AV_CODEC_ID_H264MVC:
331 // H264 Multiview Video Coding (3d blurays)
332 format = VFORMAT_H264MVC;
335 case AV_CODEC_ID_MJPEG:
336 format = VFORMAT_MJPEG;
338 case AV_CODEC_ID_VC1:
339 case AV_CODEC_ID_WMV3:
340 format = VFORMAT_VC1;
342 case AV_CODEC_ID_AVS:
343 case AV_CODEC_ID_CAVS:
344 format = VFORMAT_AVS;
348 format = VFORMAT_UNSUPPORT;
352 CLog::Log(LOGDEBUG, "codecid_to_vformat, id(%d) -> vformat(%d)", (int)id, format);
356 static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag)
358 vdec_type_t dec_type;
361 case CODEC_TAG_MJPEG:
362 case CODEC_TAG_mjpeg:
366 dec_type = VIDEO_DEC_FORMAT_MJPEG;
372 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
378 dec_type = VIDEO_DEC_FORMAT_MPEG4_3;
383 dec_type = VIDEO_DEC_FORMAT_MPEG4_4;
390 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
394 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
400 case AV_CODEC_ID_MPEG4:
402 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
404 case AV_CODEC_ID_H263:
410 dec_type = VIDEO_DEC_FORMAT_H263;
416 case AV_CODEC_ID_H264:
418 dec_type = VIDEO_DEC_FORMAT_H264;
421 case AV_CODEC_ID_H264MVC:
422 dec_type = VIDEO_DEC_FORMAT_H264;
425 case AV_CODEC_ID_RV30:
428 dec_type = VIDEO_DEC_FORMAT_REAL_8;
430 case AV_CODEC_ID_RV40:
433 dec_type = VIDEO_DEC_FORMAT_REAL_9;
437 dec_type = VIDEO_DEC_FORMAT_WMV3;
439 case AV_CODEC_ID_VC1:
444 dec_type = VIDEO_DEC_FORMAT_WVC1;
446 case AV_CODEC_ID_VP6F:
448 dec_type = VIDEO_DEC_FORMAT_SW;
450 case AV_CODEC_ID_CAVS:
451 case AV_CODEC_ID_AVS:
453 dec_type = VIDEO_DEC_FORMAT_AVS;
456 dec_type = VIDEO_DEC_FORMAT_UNKNOW;
460 CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, codec_tag(%d) -> vdec_type(%d)", codec_tag, dec_type);
464 static void am_packet_init(am_packet_t *pkt)
466 memset(&pkt->avpkt, 0, sizeof(AVPacket));
481 void am_packet_release(am_packet_t *pkt)
483 if (pkt->buf != NULL)
484 free(pkt->buf), pkt->buf= NULL;
485 if (pkt->hdr != NULL)
487 if (pkt->hdr->data != NULL)
488 free(pkt->hdr->data), pkt->hdr->data = NULL;
489 free(pkt->hdr), pkt->hdr = NULL;
495 int check_in_pts(am_private_t *para, am_packet_t *pkt)
497 int last_duration = 0;
498 static int last_v_duration = 0;
501 last_duration = last_v_duration;
503 if (para->stream_type == AM_STREAM_ES) {
504 if ((int64_t)INT64_0 != pkt->avpts) {
507 if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
508 CLog::Log(LOGDEBUG, "ERROR check in pts error!");
509 return PLAYER_PTS_ERROR;
512 } else if ((int64_t)INT64_0 != pkt->avdts) {
513 pts = pkt->avdts * last_duration;
515 if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
516 CLog::Log(LOGDEBUG, "ERROR check in dts error!");
517 return PLAYER_PTS_ERROR;
520 last_v_duration = pkt->avduration ? pkt->avduration : 1;
522 if (!para->check_first_pts) {
523 if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) {
524 CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!");
525 return PLAYER_PTS_ERROR;
529 if (!para->check_first_pts) {
530 para->check_first_pts = 1;
536 return PLAYER_SUCCESS;
539 static int write_header(am_private_t *para, am_packet_t *pkt)
541 int write_bytes = 0, len = 0;
543 if (pkt->hdr && pkt->hdr->size > 0) {
544 if ((NULL == pkt->codec) || (NULL == pkt->hdr->data)) {
545 CLog::Log(LOGDEBUG, "[write_header]codec null!");
546 return PLAYER_EMPTY_P;
548 //some wvc1 es data not need to add header
549 if (para->video_format == VFORMAT_VC1 && para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
550 if ((pkt->data) && (pkt->data_size >= 4)
551 && (pkt->data[0] == 0) && (pkt->data[1] == 0)
552 && (pkt->data[2] == 1) && (pkt->data[3] == 0xd || pkt->data[3] == 0xf)) {
553 return PLAYER_SUCCESS;
557 write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len);
558 if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) {
559 if (-errno != AVERROR(EAGAIN)) {
560 CLog::Log(LOGDEBUG, "ERROR:write header failed!");
561 return PLAYER_WR_FAILED;
566 dumpfile_write(para, pkt->hdr->data, write_bytes);
568 if (len == pkt->hdr->size) {
574 return PLAYER_SUCCESS;
577 int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt)
582 int write_av_packet(am_private_t *para, am_packet_t *pkt)
584 //CLog::Log(LOGDEBUG, "write_av_packet, pkt->isvalid(%d), pkt->data(%p), pkt->data_size(%d)",
585 // pkt->isvalid, pkt->data, pkt->data_size);
587 int write_bytes = 0, len = 0, ret;
591 // do we need to check in pts or write the header ?
594 ret = check_in_pts(para, pkt);
595 if (ret != PLAYER_SUCCESS) {
596 CLog::Log(LOGDEBUG, "check in pts failed");
597 return PLAYER_WR_FAILED;
600 if (write_header(para, pkt) == PLAYER_WR_FAILED) {
601 CLog::Log(LOGDEBUG, "[%s]write header failed!", __FUNCTION__);
602 return PLAYER_WR_FAILED;
608 size = pkt->data_size ;
609 if (size == 0 && pkt->isvalid) {
614 while (size > 0 && pkt->isvalid) {
615 write_bytes = para->m_dll->codec_write(pkt->codec, buf, size);
616 if (write_bytes < 0 || write_bytes > size) {
617 CLog::Log(LOGDEBUG, "write codec data failed, write_bytes(%d), errno(%d), size(%d)", write_bytes, errno, size);
618 if (-errno != AVERROR(EAGAIN)) {
619 CLog::Log(LOGDEBUG, "write codec data failed!");
620 return PLAYER_WR_FAILED;
622 // adjust for any data we already wrote into codec.
623 // we sleep a bit then exit as we will get called again
624 // with the same pkt because pkt->isvalid has not been cleared.
626 pkt->data_size -= len;
627 usleep(RW_WAIT_TIME);
628 CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME), len(%d)", len);
629 return PLAYER_SUCCESS;
632 dumpfile_write(para, buf, write_bytes);
633 // keep track of what we write into codec from this pkt
634 // in case we get hit with EAGAIN.
636 if (len == pkt->data_size) {
640 } else if (len < pkt->data_size) {
644 // writing more that we should is a failure.
645 return PLAYER_WR_FAILED;
650 return PLAYER_SUCCESS;
653 /*************************************************************************/
654 static int m4s2_dx50_mp4v_add_header(unsigned char *buf, int size, am_packet_t *pkt)
656 if (size > pkt->hdr->size) {
657 free(pkt->hdr->data), pkt->hdr->data = NULL;
660 pkt->hdr->data = (char*)malloc(size);
661 if (!pkt->hdr->data) {
662 CLog::Log(LOGDEBUG, "[m4s2_dx50_add_header] NOMEM!");
663 return PLAYER_FAILED;
667 pkt->hdr->size = size;
668 memcpy(pkt->hdr->data, buf, size);
670 return PLAYER_SUCCESS;
673 static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt)
675 CLog::Log(LOGDEBUG, "m4s2_dx50_mp4v_write_header");
676 int ret = m4s2_dx50_mp4v_add_header(para->extradata, para->extrasize, pkt);
677 if (ret == PLAYER_SUCCESS) {
679 pkt->codec = ¶->vcodec;
681 CLog::Log(LOGDEBUG, "[m4s2_dx50_mp4v_add_header]invalid video codec!");
682 return PLAYER_EMPTY_P;
685 ret = write_av_packet(para, pkt);
690 static int mjpeg_data_prefeeding(am_packet_t *pkt)
692 const unsigned char mjpeg_addon_data[] = {
693 0xff, 0xd8, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
694 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
695 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01,
696 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10,
698 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
699 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
700 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1,
701 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
702 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
703 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
704 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
705 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
706 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
707 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
708 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,
709 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
710 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
711 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01,
712 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
713 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
714 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
715 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
716 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
717 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
718 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
719 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
720 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
721 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
722 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
723 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
724 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
725 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
728 if (pkt->hdr->data) {
729 memcpy(pkt->hdr->data, &mjpeg_addon_data, sizeof(mjpeg_addon_data));
730 pkt->hdr->size = sizeof(mjpeg_addon_data);
732 CLog::Log(LOGDEBUG, "[mjpeg_data_prefeeding]No enough memory!");
733 return PLAYER_FAILED;
735 return PLAYER_SUCCESS;
738 static int mjpeg_write_header(am_private_t *para, am_packet_t *pkt)
740 mjpeg_data_prefeeding(pkt);
742 pkt->codec = ¶->vcodec;
744 CLog::Log(LOGDEBUG, "[mjpeg_write_header]invalid codec!");
745 return PLAYER_EMPTY_P;
748 write_av_packet(para, pkt);
749 return PLAYER_SUCCESS;
752 static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h)
754 unsigned i = (w << 12) | (h & 0xfff);
755 unsigned char divx311_add[10] = {
756 0x00, 0x00, 0x00, 0x01,
757 0x20, 0x00, 0x00, 0x00,
760 divx311_add[5] = (i >> 16) & 0xff;
761 divx311_add[6] = (i >> 8) & 0xff;
762 divx311_add[7] = i & 0xff;
764 if (pkt->hdr->data) {
765 memcpy(pkt->hdr->data, divx311_add, sizeof(divx311_add));
766 pkt->hdr->size = sizeof(divx311_add);
768 CLog::Log(LOGDEBUG, "[divx3_data_prefeeding]No enough memory!");
769 return PLAYER_FAILED;
771 return PLAYER_SUCCESS;
774 static int divx3_write_header(am_private_t *para, am_packet_t *pkt)
776 CLog::Log(LOGDEBUG, "divx3_write_header");
777 divx3_data_prefeeding(pkt, para->video_width, para->video_height);
779 pkt->codec = ¶->vcodec;
781 CLog::Log(LOGDEBUG, "[divx3_write_header]invalid codec!");
782 return PLAYER_EMPTY_P;
785 write_av_packet(para, pkt);
786 return PLAYER_SUCCESS;
789 static int h264_add_header(unsigned char *buf, int size, am_packet_t *pkt)
792 if ((buf[0]==0 && buf[1]==0 && buf[2]==0 && buf[3]==1) && size < HDR_BUF_SIZE) {
793 CLog::Log(LOGDEBUG, "add four byte NAL 264 header in stream before header len=%d",size);
794 memcpy(pkt->hdr->data, buf, size);
795 pkt->hdr->size = size;
796 return PLAYER_SUCCESS;
799 if ((buf[0]==0 && buf[1]==0 && buf[2]==1) && size < HDR_BUF_SIZE) {
800 CLog::Log(LOGDEBUG, "add three byte NAL 264 header in stream before header len=%d",size);
801 memcpy(pkt->hdr->data, buf, size);
802 pkt->hdr->size = size;
803 return PLAYER_SUCCESS;
806 return PLAYER_FAILED;
808 static int h264_write_header(am_private_t *para, am_packet_t *pkt)
810 // CLog::Log(LOGDEBUG, "h264_write_header");
813 ret = h264_add_header(para->extradata, para->extrasize, pkt);
814 if (ret == PLAYER_SUCCESS) {
817 pkt->codec = ¶->vcodec;
819 //CLog::Log(LOGDEBUG, "[pre_header_feeding]invalid video codec!");
820 return PLAYER_EMPTY_P;
824 ret = write_av_packet(para, pkt);
829 static int wmv3_write_header(am_private_t *para, am_packet_t *pkt)
831 CLog::Log(LOGDEBUG, "wmv3_write_header");
832 unsigned i, check_sum = 0;
833 unsigned data_len = para->extrasize + 4;
835 pkt->hdr->data[0] = 0;
836 pkt->hdr->data[1] = 0;
837 pkt->hdr->data[2] = 1;
838 pkt->hdr->data[3] = 0x10;
840 pkt->hdr->data[4] = 0;
841 pkt->hdr->data[5] = (data_len >> 16) & 0xff;
842 pkt->hdr->data[6] = 0x88;
843 pkt->hdr->data[7] = (data_len >> 8) & 0xff;
844 pkt->hdr->data[8] = data_len & 0xff;
845 pkt->hdr->data[9] = 0x88;
847 pkt->hdr->data[10] = 0xff;
848 pkt->hdr->data[11] = 0xff;
849 pkt->hdr->data[12] = 0x88;
850 pkt->hdr->data[13] = 0xff;
851 pkt->hdr->data[14] = 0xff;
852 pkt->hdr->data[15] = 0x88;
854 for (i = 4 ; i < 16 ; i++) {
855 check_sum += pkt->hdr->data[i];
858 pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
859 pkt->hdr->data[17] = check_sum & 0xff;
860 pkt->hdr->data[18] = 0x88;
861 pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
862 pkt->hdr->data[20] = check_sum & 0xff;
863 pkt->hdr->data[21] = 0x88;
865 pkt->hdr->data[22] = (para->video_width >> 8) & 0xff;
866 pkt->hdr->data[23] = para->video_width & 0xff;
867 pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
868 pkt->hdr->data[25] = para->video_height & 0xff;
870 memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
871 pkt->hdr->size = para->extrasize + 26;
873 pkt->codec = ¶->vcodec;
875 CLog::Log(LOGDEBUG, "[wmv3_write_header]invalid codec!");
876 return PLAYER_EMPTY_P;
879 return write_av_packet(para, pkt);
882 static int wvc1_write_header(am_private_t *para, am_packet_t *pkt)
884 CLog::Log(LOGDEBUG, "wvc1_write_header");
885 memcpy(pkt->hdr->data, para->extradata + 1, para->extrasize - 1);
886 pkt->hdr->size = para->extrasize - 1;
888 pkt->codec = ¶->vcodec;
890 CLog::Log(LOGDEBUG, "[wvc1_write_header]invalid codec!");
891 return PLAYER_EMPTY_P;
894 return write_av_packet(para, pkt);
897 static int mpeg_add_header(am_private_t *para, am_packet_t *pkt)
899 CLog::Log(LOGDEBUG, "mpeg_add_header");
900 #define STUFF_BYTES_LENGTH (256)
902 unsigned char packet_wrapper[] = {
903 0x00, 0x00, 0x01, 0xe0,
904 0x00, 0x00, /* pes packet length */
906 0x20, 0x00, 0x00, 0x00, 0x00, /* PTS */
907 0x1f, 0xff, 0xff, 0xff, 0xff, /* DTS */
908 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
911 size = para->extrasize + sizeof(packet_wrapper);
912 packet_wrapper[4] = size >> 8 ;
913 packet_wrapper[5] = size & 0xff ;
914 memcpy(pkt->hdr->data, packet_wrapper, sizeof(packet_wrapper));
915 size = sizeof(packet_wrapper);
916 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper size=%d\n",__LINE__,size);
917 memcpy(pkt->hdr->data + size, para->extradata, para->extrasize);
918 size += para->extrasize;
919 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper+seq size=%d\n",__LINE__,size);
920 memset(pkt->hdr->data + size, 0xff, STUFF_BYTES_LENGTH);
921 size += STUFF_BYTES_LENGTH;
922 pkt->hdr->size = size;
923 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]hdr_size=%d\n",__LINE__,size);
925 pkt->codec = ¶->vcodec;
927 CLog::Log(LOGDEBUG, "[mpeg_add_header]invalid codec!");
928 return PLAYER_EMPTY_P;
932 return write_av_packet(para, pkt);
935 int pre_header_feeding(am_private_t *para, am_packet_t *pkt)
938 if (para->stream_type == AM_STREAM_ES) {
939 if (pkt->hdr == NULL) {
940 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
941 pkt->hdr->data = (char *)malloc(HDR_BUF_SIZE);
942 if (!pkt->hdr->data) {
943 //CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
948 if (VFORMAT_H264 == para->video_format /*|| VFORMAT_H264MVC == para->video_format*/) {
949 ret = h264_write_header(para, pkt);
950 if (ret != PLAYER_SUCCESS) {
953 } else if ((VFORMAT_MPEG4 == para->video_format) && (VIDEO_DEC_FORMAT_MPEG4_3 == para->video_codec_type)) {
954 ret = divx3_write_header(para, pkt);
955 if (ret != PLAYER_SUCCESS) {
958 } else if ((CODEC_TAG_M4S2 == para->video_codec_tag)
959 || (CODEC_TAG_DX50 == para->video_codec_tag)
960 || (CODEC_TAG_mp4v == para->video_codec_tag)) {
961 ret = m4s2_dx50_mp4v_write_header(para, pkt);
962 if (ret != PLAYER_SUCCESS) {
966 } else if ((AVI_FILE == para->file_type)
967 && (VIDEO_DEC_FORMAT_MPEG4_3 != para->vstream_info.video_codec_type)
968 && (VFORMAT_H264 != para->vstream_info.video_format)
969 && (VFORMAT_VC1 != para->vstream_info.video_format)) {
970 ret = avi_write_header(para);
971 if (ret != PLAYER_SUCCESS) {
975 } else if (CODEC_TAG_WMV3 == para->video_codec_tag) {
976 CLog::Log(LOGDEBUG, "CODEC_TAG_WMV3 == para->video_codec_tag");
977 ret = wmv3_write_header(para, pkt);
978 if (ret != PLAYER_SUCCESS) {
981 } else if ((CODEC_TAG_WVC1 == para->video_codec_tag)
982 || (CODEC_TAG_VC_1 == para->video_codec_tag)
983 || (CODEC_TAG_WMVA == para->video_codec_tag)) {
984 CLog::Log(LOGDEBUG, "CODEC_TAG_WVC1 == para->video_codec_tag");
985 ret = wvc1_write_header(para, pkt);
986 if (ret != PLAYER_SUCCESS) {
990 } else if ((MKV_FILE == para->file_type) &&
991 ((VFORMAT_MPEG4 == para->vstream_info.video_format)
992 || (VFORMAT_MPEG12 == para->vstream_info.video_format))) {
993 ret = mkv_write_header(para, pkt);
994 if (ret != PLAYER_SUCCESS) {
998 } else if (VFORMAT_MJPEG == para->video_format) {
999 ret = mjpeg_write_header(para, pkt);
1000 if (ret != PLAYER_SUCCESS) {
1006 if (pkt->hdr->data) {
1007 free(pkt->hdr->data);
1008 pkt->hdr->data = NULL;
1014 else if (para->stream_type == AM_STREAM_PS) {
1015 if (pkt->hdr == NULL) {
1016 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1017 pkt->hdr->data = (char*)malloc(HDR_BUF_SIZE);
1018 if (!pkt->hdr->data) {
1019 CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
1020 return PLAYER_NOMEM;
1023 if (( AV_CODEC_ID_MPEG1VIDEO == para->video_codec_id)
1024 || (AV_CODEC_ID_MPEG2VIDEO == para->video_codec_id)
1025 || (AV_CODEC_ID_MPEG2VIDEO_XVMC == para->video_codec_id)) {
1026 ret = mpeg_add_header(para, pkt);
1027 if (ret != PLAYER_SUCCESS) {
1032 if (pkt->hdr->data) {
1033 free(pkt->hdr->data);
1034 pkt->hdr->data = NULL;
1040 return PLAYER_SUCCESS;
1043 int divx3_prefix(am_packet_t *pkt)
1045 #define DIVX311_CHUNK_HEAD_SIZE 13
1046 const unsigned char divx311_chunk_prefix[DIVX311_CHUNK_HEAD_SIZE] = {
1047 0x00, 0x00, 0x00, 0x01, 0xb6, 'D', 'I', 'V', 'X', '3', '.', '1', '1'
1049 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1050 free(pkt->hdr->data);
1051 pkt->hdr->data = NULL;
1054 if (pkt->hdr == NULL) {
1055 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1057 CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1058 return PLAYER_FAILED;
1061 pkt->hdr->data = NULL;
1065 pkt->hdr->data = (char*)malloc(DIVX311_CHUNK_HEAD_SIZE + 4);
1066 if (pkt->hdr->data == NULL) {
1067 CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1068 return PLAYER_FAILED;
1071 memcpy(pkt->hdr->data, divx311_chunk_prefix, DIVX311_CHUNK_HEAD_SIZE);
1073 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 0] = (pkt->data_size >> 24) & 0xff;
1074 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 1] = (pkt->data_size >> 16) & 0xff;
1075 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 2] = (pkt->data_size >> 8) & 0xff;
1076 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 3] = pkt->data_size & 0xff;
1078 pkt->hdr->size = DIVX311_CHUNK_HEAD_SIZE + 4;
1081 return PLAYER_SUCCESS;
1084 int set_header_info(am_private_t *para)
1086 am_packet_t *pkt = ¶->am_pkt;
1091 // pkt->hdr->size = 0;
1093 if (para->video_format == VFORMAT_MPEG4)
1095 if (para->video_codec_type == VIDEO_DEC_FORMAT_MPEG4_3)
1097 return divx3_prefix(pkt);
1099 else if (para->video_codec_type == VIDEO_DEC_FORMAT_H263)
1101 return PLAYER_UNSUPPORT;
1102 unsigned char *vld_buf;
1103 int vld_len, vld_buf_size = para->video_width * para->video_height * 2;
1105 if (!pkt->data_size) {
1106 return PLAYER_SUCCESS;
1109 if ((pkt->data[0] == 0) && (pkt->data[1] == 0) && (pkt->data[2] == 1) && (pkt->data[3] == 0xb6)) {
1110 return PLAYER_SUCCESS;
1113 vld_buf = (unsigned char*)malloc(vld_buf_size);
1115 return PLAYER_NOMEM;
1118 if (para->flv_flag) {
1119 vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 1);
1121 if (0 == para->h263_decodable) {
1122 para->h263_decodable = para->m_dll->decodeble_h263(pkt->data);
1123 if (0 == para->h263_decodable) {
1124 CLog::Log(LOGDEBUG, "[%s]h263 unsupport video and audio, exit", __FUNCTION__);
1125 return PLAYER_UNSUPPORT;
1128 vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 0);
1136 pkt->buf_size = vld_buf_size;
1137 pkt->data = pkt->buf;
1138 pkt->data_size = vld_len;
1144 } else if (para->video_format == VFORMAT_VC1) {
1145 if (para->video_codec_type == VIDEO_DEC_FORMAT_WMV3) {
1146 unsigned i, check_sum = 0, data_len = 0;
1148 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1149 free(pkt->hdr->data);
1150 pkt->hdr->data = NULL;
1153 if (pkt->hdr == NULL) {
1154 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1156 return PLAYER_FAILED;
1159 pkt->hdr->data = NULL;
1163 if (pkt->avpkt.flags) {
1164 pkt->hdr->data = (char*)malloc(para->extrasize + 26 + 22);
1165 if (pkt->hdr->data == NULL) {
1166 return PLAYER_FAILED;
1169 pkt->hdr->data[0] = 0;
1170 pkt->hdr->data[1] = 0;
1171 pkt->hdr->data[2] = 1;
1172 pkt->hdr->data[3] = 0x10;
1174 data_len = para->extrasize + 4;
1175 pkt->hdr->data[4] = 0;
1176 pkt->hdr->data[5] = (data_len >> 16) & 0xff;
1177 pkt->hdr->data[6] = 0x88;
1178 pkt->hdr->data[7] = (data_len >> 8) & 0xff;
1179 pkt->hdr->data[8] = data_len & 0xff;
1180 pkt->hdr->data[9] = 0x88;
1182 pkt->hdr->data[10] = 0xff;
1183 pkt->hdr->data[11] = 0xff;
1184 pkt->hdr->data[12] = 0x88;
1185 pkt->hdr->data[13] = 0xff;
1186 pkt->hdr->data[14] = 0xff;
1187 pkt->hdr->data[15] = 0x88;
1189 for (i = 4 ; i < 16 ; i++) {
1190 check_sum += pkt->hdr->data[i];
1193 pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
1194 pkt->hdr->data[17] = check_sum & 0xff;
1195 pkt->hdr->data[18] = 0x88;
1196 pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
1197 pkt->hdr->data[20] = check_sum & 0xff;
1198 pkt->hdr->data[21] = 0x88;
1200 pkt->hdr->data[22] = (para->video_width >> 8) & 0xff;
1201 pkt->hdr->data[23] = para->video_width & 0xff;
1202 pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
1203 pkt->hdr->data[25] = para->video_height & 0xff;
1205 memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
1208 data_len = para->extrasize + 26;
1210 pkt->hdr->data = (char*)malloc(22);
1211 if (pkt->hdr->data == NULL) {
1212 return PLAYER_FAILED;
1216 pkt->hdr->data[data_len + 0] = 0;
1217 pkt->hdr->data[data_len + 1] = 0;
1218 pkt->hdr->data[data_len + 2] = 1;
1219 pkt->hdr->data[data_len + 3] = 0xd;
1221 pkt->hdr->data[data_len + 4] = 0;
1222 pkt->hdr->data[data_len + 5] = (pkt->data_size >> 16) & 0xff;
1223 pkt->hdr->data[data_len + 6] = 0x88;
1224 pkt->hdr->data[data_len + 7] = (pkt->data_size >> 8) & 0xff;
1225 pkt->hdr->data[data_len + 8] = pkt->data_size & 0xff;
1226 pkt->hdr->data[data_len + 9] = 0x88;
1228 pkt->hdr->data[data_len + 10] = 0xff;
1229 pkt->hdr->data[data_len + 11] = 0xff;
1230 pkt->hdr->data[data_len + 12] = 0x88;
1231 pkt->hdr->data[data_len + 13] = 0xff;
1232 pkt->hdr->data[data_len + 14] = 0xff;
1233 pkt->hdr->data[data_len + 15] = 0x88;
1235 for (i = data_len + 4 ; i < data_len + 16 ; i++) {
1236 check_sum += pkt->hdr->data[i];
1239 pkt->hdr->data[data_len + 16] = (check_sum >> 8) & 0xff;
1240 pkt->hdr->data[data_len + 17] = check_sum & 0xff;
1241 pkt->hdr->data[data_len + 18] = 0x88;
1242 pkt->hdr->data[data_len + 19] = (check_sum >> 8) & 0xff;
1243 pkt->hdr->data[data_len + 20] = check_sum & 0xff;
1244 pkt->hdr->data[data_len + 21] = 0x88;
1246 pkt->hdr->size = data_len + 22;
1248 } else if (para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
1249 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1250 free(pkt->hdr->data);
1251 pkt->hdr->data = NULL;
1254 if (pkt->hdr == NULL) {
1255 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1257 CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1258 return PLAYER_FAILED;
1261 pkt->hdr->data = NULL;
1265 pkt->hdr->data = (char*)malloc(4);
1266 if (pkt->hdr->data == NULL) {
1267 CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1268 return PLAYER_FAILED;
1271 pkt->hdr->data[0] = 0;
1272 pkt->hdr->data[1] = 0;
1273 pkt->hdr->data[2] = 1;
1274 pkt->hdr->data[3] = 0xd;
1280 return PLAYER_SUCCESS;
1283 /*************************************************************************/
1284 CAMLCodec::CAMLCodec() : CThread("CAMLCodec")
1287 am_private = new am_private_t;
1288 memset(am_private, 0, sizeof(am_private_t));
1289 m_dll = new DllLibAmCodec;
1291 am_private->m_dll = m_dll;
1295 CAMLCodec::~CAMLCodec()
1300 delete m_dll, m_dll = NULL;
1303 bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
1305 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder");
1306 m_speed = DVD_PLAYSPEED_NORMAL;
1311 m_dst_rect.SetRect(0, 0, 0, 0);
1315 m_vbufsize = 500000 * 2;
1320 ShowMainVideo(false);
1322 am_packet_init(&am_private->am_pkt);
1323 // default stream type
1324 am_private->stream_type = AM_STREAM_ES;
1326 am_private->video_width = hints.width;
1327 am_private->video_height = hints.height;
1328 am_private->video_codec_id = hints.codec;
1329 am_private->video_codec_tag = hints.codec_tag;
1330 am_private->video_pid = hints.pid;
1332 // handle video ratio
1333 AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX);
1334 //if (!hints.forced_aspect)
1335 // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX);
1336 am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den;
1337 am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den;
1339 // handle video rate
1340 if (hints.rfpsrate > 0 && hints.rfpsscale != 0)
1342 // check ffmpeg r_frame_rate 1st
1343 am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate;
1345 else if (hints.fpsrate > 0 && hints.fpsscale != 0)
1347 // then ffmpeg avg_frame_rate next
1348 am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate;
1351 // check for 1920x1080, interlaced, 25 fps
1352 // incorrectly reported as 50 fps (yes, video_rate == 1920)
1353 if (hints.width == 1920 && am_private->video_rate == 1920)
1355 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1356 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000;
1359 // check for SD h264 content incorrectly reported as 60 fsp
1360 // mp4/avi containers :(
1361 if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 1602)
1363 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1364 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1367 // check for SD h264 content incorrectly reported as some form of 30 fsp
1368 // mp4/avi containers :(
1369 if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720)
1371 if (am_private->video_rate >= 3200 && am_private->video_rate <= 3210)
1373 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1374 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1378 // handle orientation
1379 am_private->video_rotation_degree = 0;
1380 if (hints.orientation == 90)
1381 am_private->video_rotation_degree = 1;
1382 else if (hints.orientation == 180)
1383 am_private->video_rotation_degree = 2;
1384 else if (hints.orientation == 270)
1385 am_private->video_rotation_degree = 3;
1387 am_private->video_format = codecid_to_vformat(hints.codec);
1388 switch (am_private->video_format)
1391 am_private->extrasize = hints.extrasize;
1392 am_private->extradata = (uint8_t*)malloc(hints.extrasize);
1393 memcpy(am_private->extradata, hints.extradata, hints.extrasize);
1396 case VFORMAT_MPEG12:
1400 if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0)
1401 am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag);
1403 am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id);
1405 am_private->flv_flag = 0;
1406 if (am_private->video_codec_id == AV_CODEC_ID_FLV1)
1408 am_private->video_codec_tag = CODEC_TAG_F263;
1409 am_private->flv_flag = 1;
1412 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder "
1413 "hints.width(%d), hints.height(%d), hints.codec(%d), hints.codec_tag(%d), hints.pid(%d)",
1414 hints.width, hints.height, hints.codec, hints.codec_tag, hints.pid);
1415 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)",
1416 hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate);
1417 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)",
1418 hints.aspect, video_ratio.num, video_ratio.den);
1419 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)",
1420 hints.orientation, hints.forced_aspect, hints.extrasize);
1422 // default video codec params
1423 am_private->vcodec.has_video = 1;
1424 am_private->vcodec.noblock = 0;
1425 am_private->vcodec.video_pid = am_private->video_pid;
1426 am_private->vcodec.video_type = am_private->video_format;
1427 am_private->vcodec.stream_type = STREAM_TYPE_ES_VIDEO;
1428 am_private->vcodec.am_sysinfo.format = am_private->video_codec_type;
1429 am_private->vcodec.am_sysinfo.width = am_private->video_width;
1430 am_private->vcodec.am_sysinfo.height = am_private->video_height;
1431 am_private->vcodec.am_sysinfo.rate = am_private->video_rate;
1432 am_private->vcodec.am_sysinfo.ratio = am_private->video_ratio;
1433 am_private->vcodec.am_sysinfo.ratio64 = am_private->video_ratio64;
1434 am_private->vcodec.am_sysinfo.param = NULL;
1436 switch(am_private->video_format)
1441 am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS;
1444 case VFORMAT_H264MVC:
1445 am_private->vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264;
1446 am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS;
1447 // h264 in an avi file
1448 if (m_hints.ptsinvalid)
1449 am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
1452 am_private->stream_type = AM_STREAM_RM;
1453 am_private->vcodec.noblock = 1;
1454 am_private->vcodec.stream_type = STREAM_TYPE_RM;
1455 am_private->vcodec.am_sysinfo.ratio = 0x100;
1456 am_private->vcodec.am_sysinfo.ratio64 = 0;
1458 static unsigned short tbl[9] = {0};
1459 if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type)
1461 am_private->vcodec.am_sysinfo.extra = am_private->extradata[1] & 7;
1462 tbl[0] = (((am_private->vcodec.am_sysinfo.width >> 2) - 1) << 8)
1463 | (((am_private->vcodec.am_sysinfo.height >> 2) - 1) & 0xff);
1465 for (unsigned int i = 1; i <= am_private->vcodec.am_sysinfo.extra; i++)
1468 tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff);
1471 am_private->vcodec.am_sysinfo.param = &tbl;
1475 // vc1 in an avi file
1476 if (m_hints.ptsinvalid)
1477 am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS;
1480 am_private->vcodec.am_sysinfo.param = (void *)((unsigned int)am_private->vcodec.am_sysinfo.param | (am_private->video_rotation_degree << 16));
1482 int ret = m_dll->codec_init(&am_private->vcodec);
1483 if (ret != CODEC_ERROR_NONE)
1485 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret);
1488 am_private->dumpdemux = false;
1489 dumpfile_open(am_private);
1491 // make sure we are not stuck in pause (amcodec bug)
1492 m_dll->codec_resume(&am_private->vcodec);
1493 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1495 m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH);
1496 m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0);
1497 // disable tsync, we are playing video disconnected from audio.
1498 aml_set_sysfs_int("/sys/class/tsync/enable", 0);
1500 am_private->am_pkt.codec = &am_private->vcodec;
1501 pre_header_feeding(am_private, &am_private->am_pkt);
1505 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1506 g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack);
1509 // if display is set to 1080xxx, then disable deinterlacer for HD content
1510 // else bandwidth usage is too heavy and it will slow down video decoder.
1511 char display_mode[256] = {0};
1512 aml_get_sysfs_str("/sys/class/display/mode", display_mode, 255);
1513 if (strstr(display_mode,"1080"))
1514 aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 1);
1516 aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 0);
1520 // vcodec is open, update speed if it was
1521 // changed before dvdplayer called OpenDecoder.
1527 void CAMLCodec::CloseDecoder()
1529 CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder");
1532 g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL);
1533 g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL);
1535 // never leave vcodec ff/rw or paused.
1536 if (m_speed != DVD_PLAYSPEED_NORMAL)
1538 m_dll->codec_resume(&am_private->vcodec);
1539 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1541 m_dll->codec_close(&am_private->vcodec);
1542 dumpfile_close(am_private);
1545 am_packet_release(&am_private->am_pkt);
1546 free(am_private->extradata);
1547 am_private->extradata = NULL;
1548 // return tsync to default so external apps work
1549 aml_set_sysfs_int("/sys/class/tsync/enable", 1);
1551 ShowMainVideo(false);
1555 void CAMLCodec::Reset()
1557 CLog::Log(LOGDEBUG, "CAMLCodec::Reset");
1562 // set the system blackout_policy to leave the last frame showing
1563 int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy");
1564 aml_set_sysfs_int("/sys/class/video/blackout_policy", 0);
1566 // restore the speed (some amcodec versions require this)
1567 if (m_speed != DVD_PLAYSPEED_NORMAL)
1569 m_dll->codec_resume(&am_private->vcodec);
1570 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1572 // reset the decoder
1573 m_dll->codec_reset(&am_private->vcodec);
1574 dumpfile_close(am_private);
1575 dumpfile_open(am_private);
1577 // re-init our am_pkt
1578 am_packet_release(&am_private->am_pkt);
1579 am_packet_init(&am_private->am_pkt);
1580 am_private->am_pkt.codec = &am_private->vcodec;
1581 pre_header_feeding(am_private, &am_private->am_pkt);
1583 // restore the saved system blackout_policy value
1584 aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy);
1586 // reset some interal vars
1594 int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
1599 // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during
1600 // g_renderManager.Configure call by player, which happens after the codec
1601 // OpenDecoder call. So we need to restore it but it does not seem to stick :)
1602 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1606 am_private->am_pkt.data = pData;
1607 am_private->am_pkt.data_size = iSize;
1609 am_private->am_pkt.newflag = 1;
1610 am_private->am_pkt.isvalid = 1;
1611 am_private->am_pkt.avduration = 0;
1613 // handle pts, including 31bit wrap, aml can only handle 31
1614 // bit pts as it uses an int in kernel.
1615 if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE)
1616 am_private->am_pkt.avpts = AV_NOPTS_VALUE;
1619 am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\
1620 if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff)
1621 m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff;
1623 if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE)
1624 am_private->am_pkt.avpts -= m_start_pts;
1627 // handle dts, including 31bit wrap, aml can only handle 31
1628 // bit dts as it uses an int in kernel.
1629 if (dts == DVD_NOPTS_VALUE)
1630 am_private->am_pkt.avdts = AV_NOPTS_VALUE;
1633 am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE;
1634 if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff)
1635 m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff;
1637 if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE)
1638 am_private->am_pkt.avdts -= m_start_dts;
1640 //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)",
1641 // iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts);
1643 // some formats need header/data tweaks.
1644 // the actual write occurs once in write_av_packet
1645 // and is controlled by am_pkt.newflag.
1646 set_header_info(am_private);
1648 // loop until we write all into codec, am_pkt.isvalid
1649 // will get set to zero once everything is consumed.
1650 // PLAYER_SUCCESS means all is ok, not all bytes were written.
1651 while (am_private->am_pkt.isvalid)
1653 // abort on any errors.
1654 if (write_av_packet(am_private, &am_private->am_pkt) != PLAYER_SUCCESS)
1657 if (am_private->am_pkt.isvalid)
1658 CLog::Log(LOGDEBUG, "CAMLCodec::Decode: write_av_packet looping");
1661 // if we seek, then GetTimeSize is wrong as
1662 // reports lastpts - cur_pts and hw decoder has
1663 // not started outputing new pts values yet.
1664 // so we grab the 1st pts sent into driver and
1665 // use that to calc GetTimeSize.
1667 m_1st_pts = am_private->am_pkt.lastpts;
1670 // if we have still frames, demux size will be small
1671 // and we need to pre-buffer more.
1672 double target_timesize = 1.0;
1674 target_timesize = 2.0;
1676 // keep hw buffered demux above 1 second
1677 if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL)
1680 // wait until we get a new frame or 25ms,
1681 if (m_old_pictcnt == m_cur_pictcnt)
1682 m_ready_event.WaitMSec(25);
1684 // we must return VC_BUFFER or VC_PICTURE,
1685 // default to VC_BUFFER.
1686 int rtn = VC_BUFFER;
1687 if (m_old_pictcnt != m_cur_pictcnt)
1691 // we got a new pict, try and keep hw buffered demux above 2 seconds.
1692 // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds.
1693 // we also check to make sure we keep from filling hw buffer.
1694 if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3)
1698 CLog::Log(LOGDEBUG, "CAMLCodec::Decode: "
1699 "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)",
1700 rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize());
1705 bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture)
1710 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
1711 pDvdVideoPicture->format = RENDER_FMT_BYPASS;
1712 pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
1714 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
1715 pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE;
1716 // video pts cannot be late or dvdplayer goes nuts,
1717 // so run it one frame ahead
1718 pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration;
1723 void CAMLCodec::SetSpeed(int speed)
1725 CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed);
1727 // update internal vars regardless
1728 // of if we are open or not.
1736 case DVD_PLAYSPEED_PAUSE:
1737 m_dll->codec_pause(&am_private->vcodec);
1738 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1740 case DVD_PLAYSPEED_NORMAL:
1741 m_dll->codec_resume(&am_private->vcodec);
1742 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1745 m_dll->codec_resume(&am_private->vcodec);
1746 if (am_private->video_format == VFORMAT_H264)
1747 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB);
1749 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I);
1754 int CAMLCodec::GetDataSize()
1759 struct buf_status vbuf ={0};
1760 if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0)
1761 m_vbufsize = vbuf.size;
1763 return vbuf.data_len;
1766 double CAMLCodec::GetTimeSize()
1771 // if m_cur_pts is zero, hw decoder was not started yet
1772 // so we use the pts of the 1st demux packet that was send
1773 // to hw decoder to calc timesize.
1775 m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ;
1777 m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ;
1779 // lie to DVDPlayer, it is hardcoded to a max of 8 seconds,
1780 // if you buffer more than 8 seconds, it goes nuts.
1781 double timesize = m_timesize;
1784 else if (timesize > 7.0)
1790 void CAMLCodec::Process()
1792 CLog::Log(LOGDEBUG, "CAMLCodec::Process Started");
1794 // bump our priority to be level with SoftAE
1795 SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
1798 int64_t pts_video = 0;
1799 if (am_private->am_pkt.lastpts > 0)
1801 // this is a blocking poll that returns every vsync.
1802 // since we are running at a higher priority, make sure
1803 // we sleep if the call fails or does a timeout.
1804 if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0)
1806 CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed");
1810 pts_video = get_pts_video();
1811 if (m_cur_pts != pts_video)
1813 //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)",
1814 // pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ));
1816 // other threads look at these, do them first
1817 m_cur_pts = pts_video;
1819 m_ready_event.Set();
1821 // correct video pts by starting pts.
1822 if (m_start_pts != 0)
1823 pts_video += m_start_pts;
1824 else if (m_start_dts != 0)
1825 pts_video += m_start_dts;
1827 double app_pts = GetPlayerPtsSeconds();
1828 // add in audio delay/display latency contribution
1829 double offset = g_renderManager.GetDisplayLatency() - CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay;
1830 // correct video pts by user set delay and rendering delay
1833 //CLog::Log(LOGDEBUG, "CAMLCodec::Process: app_pts(%f), pts_video/PTS_FREQ(%f)",
1834 // app_pts, (double)pts_video/PTS_FREQ);
1836 double error = app_pts - (double)pts_video/PTS_FREQ;
1837 double abs_error = fabs(error);
1838 if (abs_error > 0.150)
1840 //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error);
1841 if (abs_error > 0.125)
1843 // big error so try to reset pts_pcrscr
1844 SetVideoPtsSeconds(app_pts);
1848 // small error so try to avoid a frame jump
1849 SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4);
1859 SetPriority(THREAD_PRIORITY_NORMAL);
1860 CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped");
1863 double CAMLCodec::GetPlayerPtsSeconds()
1865 double clock_pts = 0.0;
1866 CDVDClock *playerclock = CDVDClock::GetMasterClock();
1868 clock_pts = playerclock->GetClock() / DVD_TIME_BASE;
1873 void CAMLCodec::SetVideoPtsSeconds(const double pts)
1875 //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts);
1878 int64_t pts_video = (int64_t)(pts * PTS_FREQ);
1879 if (m_start_pts != 0)
1880 pts_video -= m_start_pts;
1881 else if (m_start_dts != 0)
1882 pts_video -= m_start_dts;
1884 set_pts_pcrscr(pts_video);
1888 void CAMLCodec::ShowMainVideo(const bool show)
1890 static int saved_disable_video = -1;
1892 int disable_video = show ? 0:1;
1893 if (saved_disable_video == disable_video)
1896 aml_set_sysfs_int("/sys/class/video/disable_video", disable_video);
1897 saved_disable_video = disable_video;
1900 void CAMLCodec::SetVideoZoom(const float zoom)
1902 // input zoom range is 0.5 to 2.0 with a default of 1.0.
1903 // output zoom range is 2 to 300 with default of 100.
1904 // we limit that to a range of 50 to 200 with default of 100.
1905 aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom));
1908 void CAMLCodec::SetVideoContrast(const int contrast)
1910 // input contrast range is 0 to 100 with default of 50.
1911 // output contrast range is -255 to 255 with default of 0.
1912 int aml_contrast = (255 * (contrast - 50)) / 50;
1913 aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast);
1915 void CAMLCodec::SetVideoBrightness(const int brightness)
1917 // input brightness range is 0 to 100 with default of 50.
1918 // output brightness range is -127 to 127 with default of 0.
1919 int aml_brightness = (127 * (brightness - 50)) / 50;
1920 aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness);
1922 void CAMLCodec::SetVideoSaturation(const int saturation)
1924 // output saturation range is -127 to 127 with default of 127.
1925 aml_set_sysfs_int("/sys/class/video/saturation", saturation);
1928 void CAMLCodec::GetRenderFeatures(Features &renderFeatures)
1930 renderFeatures.push_back(RENDERFEATURE_ZOOM);
1931 renderFeatures.push_back(RENDERFEATURE_CONTRAST);
1932 renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS);
1933 renderFeatures.push_back(RENDERFEATURE_STRETCH);
1934 renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO);
1938 void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures)
1940 CAMLCodec *codec = (CAMLCodec*)ctx;
1942 codec->GetRenderFeatures(renderFeatures);
1945 void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
1947 // this routine gets called every video frame
1948 // and is in the context of the renderer thread so
1949 // do not do anything stupid here.
1951 // video zoom adjustment.
1952 float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount;
1953 if ((int)(zoom * 1000) != (int)(m_zoom * 1000))
1957 // video contrast adjustment.
1958 int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast;
1959 if (contrast != m_contrast)
1961 SetVideoContrast(contrast);
1962 m_contrast = contrast;
1964 // video brightness adjustment.
1965 int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness;
1966 if (brightness != m_brightness)
1968 SetVideoBrightness(brightness);
1969 m_brightness = brightness;
1972 // check if destination rect or video view mode has changed
1973 if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode))
1975 m_dst_rect = DestRect;
1976 m_view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
1980 // mainvideo 'should' be showing already if we get here, make sure.
1981 ShowMainVideo(true);
1985 CRect gui, display, dst_rect;
1986 gui = g_graphicsContext.GetViewWindow();
1987 // when display is at 1080p, we have freescale enabled
1988 // and that scales all layers into 1080p display including video,
1989 // so we have to setup video axis for 720p instead of 1080p... Boooo.
1990 display = g_graphicsContext.GetViewWindow();
1991 dst_rect = m_dst_rect;
1994 float xscale = display.Width() / gui.Width();
1995 float yscale = display.Height() / gui.Height();
1996 dst_rect.x1 *= xscale;
1997 dst_rect.x2 *= xscale;
1998 dst_rect.y1 *= yscale;
1999 dst_rect.y2 *= yscale;
2002 ShowMainVideo(false);
2004 // goofy 0/1 based difference in aml axis coordinates.
2009 char video_axis[256] = {0};
2010 sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2);
2011 aml_set_sysfs_str("/sys/class/video/axis", video_axis);
2012 // make sure we are in 'full stretch' so we can stretch
2013 aml_set_sysfs_int("/sys/class/video/screen_mode", 1);
2016 CStdString rectangle;
2017 rectangle.Format("%i,%i,%i,%i",
2018 (int)dst_rect.x1, (int)dst_rect.y1,
2019 (int)dst_rect.Width(), (int)dst_rect.Height());
2020 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str());
2023 // we only get called once gui has changed to something
2024 // that would show video playback, so show it.
2025 ShowMainVideo(true);
2028 void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
2030 CAMLCodec *codec = (CAMLCodec*)ctx;
2031 codec->SetVideoRect(SrcRect, DestRect);