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/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"
37 #if defined(TARGET_ANDROID)
38 #include "android/activity/AndroidFeatures.h"
39 #include "utils/BitstreamConverter.h"
46 #include <semaphore.h>
50 #include <sys/ioctl.h>
54 #include <amcodec/codec.h>
61 stream_type_t stream_type;
69 unsigned long long ratio64;
73 class DllLibamCodecInterface
76 virtual ~DllLibamCodecInterface() {};
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;
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;
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;
98 // grab this from amffmpeg so we do not have to load DllAvUtil
99 virtual AVRational av_d2q(double d, int max)=0;
102 class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
104 // libamcodec is static linked into libamplayer.so
105 DECLARE_DLL_WRAPPER(DllLibAmCodec, "libamplayer.so")
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))
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))
123 DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4))
124 DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1))
126 DEFINE_METHOD2(AVRational, av_d2q, (double p1, int p2))
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)
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)
145 RESOLVE_METHOD(h263vld)
146 RESOLVE_METHOD(decodeble_h263)
148 RESOLVE_METHOD(av_d2q)
152 void codec_init_para(aml_generic_param *p_in, codec_para_t *p_out)
154 memset(p_out, 0x00, sizeof(codec_para_t));
156 #ifdef TARGET_ANDROID
157 bits_writer_t bs = {0};
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);
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
168 // added in JellyBean 4.2
169 if (CAndroidFeatures::GetVersion() > 16)
170 CBitstreamConverter::write_bits(&bs, 32, 0); // CODEC_HANDLE audio_utils_handle
172 CBitstreamConverter::write_bits(&bs, 32, p_in->stream_type); // stream_type_t stream_type
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
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
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
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
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);
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
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);
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;
242 //-----------------------------------------------------------------------------------
243 //-----------------------------------------------------------------------------------
244 // AppContext - Application state
245 #define MODE_3D_DISABLE 0x00000000
246 #define MODE_3D_LR 0x00000101
247 #define MODE_3D_BT 0x00000201
248 #define MODE_3D_TO_2D_L 0x00000102
249 #define MODE_3D_TO_2D_R 0x00000902
250 #define MODE_3D_TO_2D_T 0x00000202
251 #define MODE_3D_TO_2D_B 0x00000a02
253 #define PTS_FREQ 90000
254 #define UNIT_FREQ 96000
255 #define AV_SYNC_THRESH PTS_FREQ*30
257 #define TRICKMODE_NONE 0x00
258 #define TRICKMODE_I 0x01
259 #define TRICKMODE_FFFB 0x02
261 // same as AV_NOPTS_VALUE
262 #define INT64_0 INT64_C(0x8000000000000000)
264 #define EXTERNAL_PTS (1)
265 #define SYNC_OUTSIDE (2)
268 #define CODEC_TAG_VC_1 (0x312D4356)
269 #define CODEC_TAG_RV30 (0x30335652)
270 #define CODEC_TAG_RV40 (0x30345652)
271 #define CODEC_TAG_MJPEG (0x47504a4d)
272 #define CODEC_TAG_mjpeg (0x47504a4c)
273 #define CODEC_TAG_jpeg (0x6765706a)
274 #define CODEC_TAG_mjpa (0x61706a6d)
276 #define RW_WAIT_TIME (20 * 1000) // 20ms
278 #define P_PRE (0x02000000)
279 #define F_PRE (0x03000000)
280 #define PLAYER_SUCCESS (0)
281 #define PLAYER_FAILED (-(P_PRE|0x01))
282 #define PLAYER_NOMEM (-(P_PRE|0x02))
283 #define PLAYER_EMPTY_P (-(P_PRE|0x03))
285 #define PLAYER_WR_FAILED (-(P_PRE|0x21))
286 #define PLAYER_WR_EMPTYP (-(P_PRE|0x22))
287 #define PLAYER_WR_FINISH (P_PRE|0x1)
289 #define PLAYER_PTS_ERROR (-(P_PRE|0x31))
290 #define PLAYER_UNSUPPORT (-(P_PRE|0x35))
291 #define PLAYER_CHECK_CODEC_ERROR (-(P_PRE|0x39))
293 #define HDR_BUF_SIZE 1024
294 typedef struct hdr_buf {
299 typedef struct am_packet {
316 AM_STREAM_UNKNOWN = 0,
325 typedef struct am_private_t
328 aml_generic_param gcodec;
331 pstream_type stream_type;
334 vformat_t video_format;
336 unsigned int video_codec_id;
337 unsigned int video_codec_tag;
338 vdec_type_t video_codec_type;
339 unsigned int video_width;
340 unsigned int video_height;
341 unsigned int video_ratio;
342 unsigned int video_ratio64;
343 unsigned int video_rate;
344 unsigned int video_rotation_degree;
349 DllLibAmCodec *m_dll;
355 /*************************************************************************/
356 /*************************************************************************/
357 void dumpfile_open(am_private_t *para)
361 static int amcodec_dumpid = 0;
362 char dump_path[128] = {0};
363 sprintf(dump_path, "/temp/dump_amcodec-%d.dat", amcodec_dumpid++);
365 para->dumpfile = open(dump_path, O_CREAT | O_RDWR, 0666);
368 void dumpfile_close(am_private_t *para)
370 if (para->dumpdemux && para->dumpfile != -1)
371 close(para->dumpfile), para->dumpfile = -1;
373 void dumpfile_write(am_private_t *para, void* buf, int bufsiz)
377 CLog::Log(LOGERROR, "dumpfile_write: wtf ? buf is null, bufsiz(%d)", bufsiz);
381 if (para->dumpdemux && para->dumpfile != -1)
382 write(para->dumpfile, buf, bufsiz);
385 /*************************************************************************/
386 /*************************************************************************/
387 static int64_t get_pts_video()
389 int fd = open("/sys/class/tsync/pts_video", O_RDONLY);
393 int size = read(fd, pts_str, sizeof(pts_str));
397 unsigned long pts = strtoul(pts_str, NULL, 16);
402 CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error");
406 static int set_pts_pcrscr(int64_t value)
408 int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY);
412 unsigned long pts = (unsigned long)value;
413 sprintf(pts_str, "0x%lx", pts);
414 write(fd, pts_str, strlen(pts_str));
419 CLog::Log(LOGERROR, "set_pts_pcrscr: open pts_pcrscr error");
423 static vformat_t codecid_to_vformat(enum AVCodecID id)
428 case AV_CODEC_ID_MPEG1VIDEO:
429 case AV_CODEC_ID_MPEG2VIDEO:
430 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
431 format = VFORMAT_MPEG12;
433 case AV_CODEC_ID_H263:
434 case AV_CODEC_ID_MPEG4:
435 case AV_CODEC_ID_H263P:
436 case AV_CODEC_ID_H263I:
437 case AV_CODEC_ID_MSMPEG4V2:
438 case AV_CODEC_ID_MSMPEG4V3:
439 case AV_CODEC_ID_FLV1:
440 format = VFORMAT_MPEG4;
442 case AV_CODEC_ID_RV10:
443 case AV_CODEC_ID_RV20:
444 case AV_CODEC_ID_RV30:
445 case AV_CODEC_ID_RV40:
446 format = VFORMAT_REAL;
448 case AV_CODEC_ID_H264:
449 format = VFORMAT_H264;
452 case AV_CODEC_ID_H264MVC:
453 // H264 Multiview Video Coding (3d blurays)
454 format = VFORMAT_H264MVC;
457 case AV_CODEC_ID_MJPEG:
458 format = VFORMAT_MJPEG;
460 case AV_CODEC_ID_VC1:
461 case AV_CODEC_ID_WMV3:
462 format = VFORMAT_VC1;
464 case AV_CODEC_ID_AVS:
465 case AV_CODEC_ID_CAVS:
466 format = VFORMAT_AVS;
470 format = VFORMAT_UNSUPPORT;
474 CLog::Log(LOGDEBUG, "codecid_to_vformat, id(%d) -> vformat(%d)", (int)id, format);
478 static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag)
480 vdec_type_t dec_type;
483 case CODEC_TAG_MJPEG:
484 case CODEC_TAG_mjpeg:
488 dec_type = VIDEO_DEC_FORMAT_MJPEG;
494 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
500 dec_type = VIDEO_DEC_FORMAT_MPEG4_3;
505 dec_type = VIDEO_DEC_FORMAT_MPEG4_4;
512 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
516 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
522 case AV_CODEC_ID_MPEG4:
524 dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
526 case AV_CODEC_ID_H263:
532 dec_type = VIDEO_DEC_FORMAT_H263;
538 case AV_CODEC_ID_H264:
540 dec_type = VIDEO_DEC_FORMAT_H264;
543 case AV_CODEC_ID_H264MVC:
544 dec_type = VIDEO_DEC_FORMAT_H264;
547 case AV_CODEC_ID_RV30:
550 dec_type = VIDEO_DEC_FORMAT_REAL_8;
552 case AV_CODEC_ID_RV40:
555 dec_type = VIDEO_DEC_FORMAT_REAL_9;
559 dec_type = VIDEO_DEC_FORMAT_WMV3;
561 case AV_CODEC_ID_VC1:
566 dec_type = VIDEO_DEC_FORMAT_WVC1;
568 case AV_CODEC_ID_VP6F:
570 dec_type = VIDEO_DEC_FORMAT_SW;
572 case AV_CODEC_ID_CAVS:
573 case AV_CODEC_ID_AVS:
575 dec_type = VIDEO_DEC_FORMAT_AVS;
578 dec_type = VIDEO_DEC_FORMAT_UNKNOW;
582 CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, codec_tag(%d) -> vdec_type(%d)", codec_tag, dec_type);
586 static void am_packet_init(am_packet_t *pkt)
588 memset(&pkt->avpkt, 0, sizeof(AVPacket));
603 void am_packet_release(am_packet_t *pkt)
605 if (pkt->buf != NULL)
606 free(pkt->buf), pkt->buf= NULL;
607 if (pkt->hdr != NULL)
609 if (pkt->hdr->data != NULL)
610 free(pkt->hdr->data), pkt->hdr->data = NULL;
611 free(pkt->hdr), pkt->hdr = NULL;
617 int check_in_pts(am_private_t *para, am_packet_t *pkt)
619 int last_duration = 0;
620 static int last_v_duration = 0;
623 last_duration = last_v_duration;
625 if (para->stream_type == AM_STREAM_ES) {
626 if ((int64_t)INT64_0 != pkt->avpts) {
629 if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
630 CLog::Log(LOGDEBUG, "ERROR check in pts error!");
631 return PLAYER_PTS_ERROR;
634 } else if ((int64_t)INT64_0 != pkt->avdts) {
635 pts = pkt->avdts * last_duration;
637 if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
638 CLog::Log(LOGDEBUG, "ERROR check in dts error!");
639 return PLAYER_PTS_ERROR;
642 last_v_duration = pkt->avduration ? pkt->avduration : 1;
644 if (!para->check_first_pts) {
645 if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) {
646 CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!");
647 return PLAYER_PTS_ERROR;
651 if (!para->check_first_pts) {
652 para->check_first_pts = 1;
658 return PLAYER_SUCCESS;
661 static int write_header(am_private_t *para, am_packet_t *pkt)
663 int write_bytes = 0, len = 0;
665 if (pkt->hdr && pkt->hdr->size > 0) {
666 if ((NULL == pkt->codec) || (NULL == pkt->hdr->data)) {
667 CLog::Log(LOGDEBUG, "[write_header]codec null!");
668 return PLAYER_EMPTY_P;
670 //some wvc1 es data not need to add header
671 if (para->video_format == VFORMAT_VC1 && para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
672 if ((pkt->data) && (pkt->data_size >= 4)
673 && (pkt->data[0] == 0) && (pkt->data[1] == 0)
674 && (pkt->data[2] == 1) && (pkt->data[3] == 0xd || pkt->data[3] == 0xf)) {
675 return PLAYER_SUCCESS;
679 write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len);
680 if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) {
681 if (-errno != AVERROR(EAGAIN)) {
682 CLog::Log(LOGDEBUG, "ERROR:write header failed!");
683 return PLAYER_WR_FAILED;
688 dumpfile_write(para, pkt->hdr->data, write_bytes);
690 if (len == pkt->hdr->size) {
696 return PLAYER_SUCCESS;
699 int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt)
704 int write_av_packet(am_private_t *para, am_packet_t *pkt)
706 //CLog::Log(LOGDEBUG, "write_av_packet, pkt->isvalid(%d), pkt->data(%p), pkt->data_size(%d)",
707 // pkt->isvalid, pkt->data, pkt->data_size);
709 int write_bytes = 0, len = 0, ret;
713 // do we need to check in pts or write the header ?
716 ret = check_in_pts(para, pkt);
717 if (ret != PLAYER_SUCCESS) {
718 CLog::Log(LOGDEBUG, "check in pts failed");
719 return PLAYER_WR_FAILED;
722 if (write_header(para, pkt) == PLAYER_WR_FAILED) {
723 CLog::Log(LOGDEBUG, "[%s]write header failed!", __FUNCTION__);
724 return PLAYER_WR_FAILED;
730 size = pkt->data_size ;
731 if (size == 0 && pkt->isvalid) {
736 while (size > 0 && pkt->isvalid) {
737 write_bytes = para->m_dll->codec_write(pkt->codec, buf, size);
738 if (write_bytes < 0 || write_bytes > size) {
739 CLog::Log(LOGDEBUG, "write codec data failed, write_bytes(%d), errno(%d), size(%d)", write_bytes, errno, size);
740 if (-errno != AVERROR(EAGAIN)) {
741 CLog::Log(LOGDEBUG, "write codec data failed!");
742 return PLAYER_WR_FAILED;
744 // adjust for any data we already wrote into codec.
745 // we sleep a bit then exit as we will get called again
746 // with the same pkt because pkt->isvalid has not been cleared.
748 pkt->data_size -= len;
749 usleep(RW_WAIT_TIME);
750 CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME), len(%d)", len);
751 return PLAYER_SUCCESS;
754 dumpfile_write(para, buf, write_bytes);
755 // keep track of what we write into codec from this pkt
756 // in case we get hit with EAGAIN.
758 if (len == pkt->data_size) {
762 } else if (len < pkt->data_size) {
766 // writing more that we should is a failure.
767 return PLAYER_WR_FAILED;
772 return PLAYER_SUCCESS;
775 /*************************************************************************/
776 static int m4s2_dx50_mp4v_add_header(unsigned char *buf, int size, am_packet_t *pkt)
778 if (size > pkt->hdr->size) {
779 free(pkt->hdr->data), pkt->hdr->data = NULL;
782 pkt->hdr->data = (char*)malloc(size);
783 if (!pkt->hdr->data) {
784 CLog::Log(LOGDEBUG, "[m4s2_dx50_add_header] NOMEM!");
785 return PLAYER_FAILED;
789 pkt->hdr->size = size;
790 memcpy(pkt->hdr->data, buf, size);
792 return PLAYER_SUCCESS;
795 static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt)
797 CLog::Log(LOGDEBUG, "m4s2_dx50_mp4v_write_header");
798 int ret = m4s2_dx50_mp4v_add_header(para->extradata, para->extrasize, pkt);
799 if (ret == PLAYER_SUCCESS) {
801 pkt->codec = ¶->vcodec;
803 CLog::Log(LOGDEBUG, "[m4s2_dx50_mp4v_add_header]invalid video codec!");
804 return PLAYER_EMPTY_P;
807 ret = write_av_packet(para, pkt);
812 static int mjpeg_data_prefeeding(am_packet_t *pkt)
814 const unsigned char mjpeg_addon_data[] = {
815 0xff, 0xd8, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
816 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
817 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01,
818 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10,
820 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
821 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
822 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1,
823 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
824 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
825 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
826 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
827 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
828 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
829 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
830 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,
831 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
832 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
833 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01,
834 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
835 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
836 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
837 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
838 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
839 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
840 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
841 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
842 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
843 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
844 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
845 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
846 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
847 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
850 if (pkt->hdr->data) {
851 memcpy(pkt->hdr->data, &mjpeg_addon_data, sizeof(mjpeg_addon_data));
852 pkt->hdr->size = sizeof(mjpeg_addon_data);
854 CLog::Log(LOGDEBUG, "[mjpeg_data_prefeeding]No enough memory!");
855 return PLAYER_FAILED;
857 return PLAYER_SUCCESS;
860 static int mjpeg_write_header(am_private_t *para, am_packet_t *pkt)
862 mjpeg_data_prefeeding(pkt);
864 pkt->codec = ¶->vcodec;
866 CLog::Log(LOGDEBUG, "[mjpeg_write_header]invalid codec!");
867 return PLAYER_EMPTY_P;
870 write_av_packet(para, pkt);
871 return PLAYER_SUCCESS;
874 static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h)
876 unsigned i = (w << 12) | (h & 0xfff);
877 unsigned char divx311_add[10] = {
878 0x00, 0x00, 0x00, 0x01,
879 0x20, 0x00, 0x00, 0x00,
882 divx311_add[5] = (i >> 16) & 0xff;
883 divx311_add[6] = (i >> 8) & 0xff;
884 divx311_add[7] = i & 0xff;
886 if (pkt->hdr->data) {
887 memcpy(pkt->hdr->data, divx311_add, sizeof(divx311_add));
888 pkt->hdr->size = sizeof(divx311_add);
890 CLog::Log(LOGDEBUG, "[divx3_data_prefeeding]No enough memory!");
891 return PLAYER_FAILED;
893 return PLAYER_SUCCESS;
896 static int divx3_write_header(am_private_t *para, am_packet_t *pkt)
898 CLog::Log(LOGDEBUG, "divx3_write_header");
899 divx3_data_prefeeding(pkt, para->video_width, para->video_height);
901 pkt->codec = ¶->vcodec;
903 CLog::Log(LOGDEBUG, "[divx3_write_header]invalid codec!");
904 return PLAYER_EMPTY_P;
907 write_av_packet(para, pkt);
908 return PLAYER_SUCCESS;
911 static int h264_add_header(unsigned char *buf, int size, am_packet_t *pkt)
914 if ((buf[0]==0 && buf[1]==0 && buf[2]==0 && buf[3]==1) && size < HDR_BUF_SIZE) {
915 CLog::Log(LOGDEBUG, "add four byte NAL 264 header in stream before header len=%d",size);
916 memcpy(pkt->hdr->data, buf, size);
917 pkt->hdr->size = size;
918 return PLAYER_SUCCESS;
921 if ((buf[0]==0 && buf[1]==0 && buf[2]==1) && size < HDR_BUF_SIZE) {
922 CLog::Log(LOGDEBUG, "add three byte NAL 264 header in stream before header len=%d",size);
923 memcpy(pkt->hdr->data, buf, size);
924 pkt->hdr->size = size;
925 return PLAYER_SUCCESS;
928 return PLAYER_FAILED;
930 static int h264_write_header(am_private_t *para, am_packet_t *pkt)
932 // CLog::Log(LOGDEBUG, "h264_write_header");
935 ret = h264_add_header(para->extradata, para->extrasize, pkt);
936 if (ret == PLAYER_SUCCESS) {
939 pkt->codec = ¶->vcodec;
941 //CLog::Log(LOGDEBUG, "[pre_header_feeding]invalid video codec!");
942 return PLAYER_EMPTY_P;
946 ret = write_av_packet(para, pkt);
951 static int wmv3_write_header(am_private_t *para, am_packet_t *pkt)
953 CLog::Log(LOGDEBUG, "wmv3_write_header");
954 unsigned i, check_sum = 0;
955 unsigned data_len = para->extrasize + 4;
957 pkt->hdr->data[0] = 0;
958 pkt->hdr->data[1] = 0;
959 pkt->hdr->data[2] = 1;
960 pkt->hdr->data[3] = 0x10;
962 pkt->hdr->data[4] = 0;
963 pkt->hdr->data[5] = (data_len >> 16) & 0xff;
964 pkt->hdr->data[6] = 0x88;
965 pkt->hdr->data[7] = (data_len >> 8) & 0xff;
966 pkt->hdr->data[8] = data_len & 0xff;
967 pkt->hdr->data[9] = 0x88;
969 pkt->hdr->data[10] = 0xff;
970 pkt->hdr->data[11] = 0xff;
971 pkt->hdr->data[12] = 0x88;
972 pkt->hdr->data[13] = 0xff;
973 pkt->hdr->data[14] = 0xff;
974 pkt->hdr->data[15] = 0x88;
976 for (i = 4 ; i < 16 ; i++) {
977 check_sum += pkt->hdr->data[i];
980 pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
981 pkt->hdr->data[17] = check_sum & 0xff;
982 pkt->hdr->data[18] = 0x88;
983 pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
984 pkt->hdr->data[20] = check_sum & 0xff;
985 pkt->hdr->data[21] = 0x88;
987 pkt->hdr->data[22] = (para->video_width >> 8) & 0xff;
988 pkt->hdr->data[23] = para->video_width & 0xff;
989 pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
990 pkt->hdr->data[25] = para->video_height & 0xff;
992 memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
993 pkt->hdr->size = para->extrasize + 26;
995 pkt->codec = ¶->vcodec;
997 CLog::Log(LOGDEBUG, "[wmv3_write_header]invalid codec!");
998 return PLAYER_EMPTY_P;
1001 return write_av_packet(para, pkt);
1004 static int wvc1_write_header(am_private_t *para, am_packet_t *pkt)
1006 CLog::Log(LOGDEBUG, "wvc1_write_header");
1007 memcpy(pkt->hdr->data, para->extradata + 1, para->extrasize - 1);
1008 pkt->hdr->size = para->extrasize - 1;
1010 pkt->codec = ¶->vcodec;
1012 CLog::Log(LOGDEBUG, "[wvc1_write_header]invalid codec!");
1013 return PLAYER_EMPTY_P;
1016 return write_av_packet(para, pkt);
1019 static int mpeg_add_header(am_private_t *para, am_packet_t *pkt)
1021 CLog::Log(LOGDEBUG, "mpeg_add_header");
1022 #define STUFF_BYTES_LENGTH (256)
1024 unsigned char packet_wrapper[] = {
1025 0x00, 0x00, 0x01, 0xe0,
1026 0x00, 0x00, /* pes packet length */
1028 0x20, 0x00, 0x00, 0x00, 0x00, /* PTS */
1029 0x1f, 0xff, 0xff, 0xff, 0xff, /* DTS */
1030 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1033 size = para->extrasize + sizeof(packet_wrapper);
1034 packet_wrapper[4] = size >> 8 ;
1035 packet_wrapper[5] = size & 0xff ;
1036 memcpy(pkt->hdr->data, packet_wrapper, sizeof(packet_wrapper));
1037 size = sizeof(packet_wrapper);
1038 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper size=%d\n",__LINE__,size);
1039 memcpy(pkt->hdr->data + size, para->extradata, para->extrasize);
1040 size += para->extrasize;
1041 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper+seq size=%d\n",__LINE__,size);
1042 memset(pkt->hdr->data + size, 0xff, STUFF_BYTES_LENGTH);
1043 size += STUFF_BYTES_LENGTH;
1044 pkt->hdr->size = size;
1045 //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]hdr_size=%d\n",__LINE__,size);
1047 pkt->codec = ¶->vcodec;
1049 CLog::Log(LOGDEBUG, "[mpeg_add_header]invalid codec!");
1050 return PLAYER_EMPTY_P;
1054 return write_av_packet(para, pkt);
1057 int pre_header_feeding(am_private_t *para, am_packet_t *pkt)
1060 if (para->stream_type == AM_STREAM_ES) {
1061 if (pkt->hdr == NULL) {
1062 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1063 pkt->hdr->data = (char *)malloc(HDR_BUF_SIZE);
1064 if (!pkt->hdr->data) {
1065 //CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
1066 return PLAYER_NOMEM;
1070 if (VFORMAT_H264 == para->video_format /*|| VFORMAT_H264MVC == para->video_format*/) {
1071 ret = h264_write_header(para, pkt);
1072 if (ret != PLAYER_SUCCESS) {
1075 } else if ((VFORMAT_MPEG4 == para->video_format) && (VIDEO_DEC_FORMAT_MPEG4_3 == para->video_codec_type)) {
1076 ret = divx3_write_header(para, pkt);
1077 if (ret != PLAYER_SUCCESS) {
1080 } else if ((CODEC_TAG_M4S2 == para->video_codec_tag)
1081 || (CODEC_TAG_DX50 == para->video_codec_tag)
1082 || (CODEC_TAG_mp4v == para->video_codec_tag)) {
1083 ret = m4s2_dx50_mp4v_write_header(para, pkt);
1084 if (ret != PLAYER_SUCCESS) {
1088 } else if ((AVI_FILE == para->file_type)
1089 && (VIDEO_DEC_FORMAT_MPEG4_3 != para->vstream_info.video_codec_type)
1090 && (VFORMAT_H264 != para->vstream_info.video_format)
1091 && (VFORMAT_VC1 != para->vstream_info.video_format)) {
1092 ret = avi_write_header(para);
1093 if (ret != PLAYER_SUCCESS) {
1097 } else if (CODEC_TAG_WMV3 == para->video_codec_tag) {
1098 CLog::Log(LOGDEBUG, "CODEC_TAG_WMV3 == para->video_codec_tag");
1099 ret = wmv3_write_header(para, pkt);
1100 if (ret != PLAYER_SUCCESS) {
1103 } else if ((CODEC_TAG_WVC1 == para->video_codec_tag)
1104 || (CODEC_TAG_VC_1 == para->video_codec_tag)
1105 || (CODEC_TAG_WMVA == para->video_codec_tag)) {
1106 CLog::Log(LOGDEBUG, "CODEC_TAG_WVC1 == para->video_codec_tag");
1107 ret = wvc1_write_header(para, pkt);
1108 if (ret != PLAYER_SUCCESS) {
1112 } else if ((MKV_FILE == para->file_type) &&
1113 ((VFORMAT_MPEG4 == para->vstream_info.video_format)
1114 || (VFORMAT_MPEG12 == para->vstream_info.video_format))) {
1115 ret = mkv_write_header(para, pkt);
1116 if (ret != PLAYER_SUCCESS) {
1120 } else if (VFORMAT_MJPEG == para->video_format) {
1121 ret = mjpeg_write_header(para, pkt);
1122 if (ret != PLAYER_SUCCESS) {
1128 if (pkt->hdr->data) {
1129 free(pkt->hdr->data);
1130 pkt->hdr->data = NULL;
1136 else if (para->stream_type == AM_STREAM_PS) {
1137 if (pkt->hdr == NULL) {
1138 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1139 pkt->hdr->data = (char*)malloc(HDR_BUF_SIZE);
1140 if (!pkt->hdr->data) {
1141 CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!");
1142 return PLAYER_NOMEM;
1145 if (( AV_CODEC_ID_MPEG1VIDEO == para->video_codec_id)
1146 || (AV_CODEC_ID_MPEG2VIDEO == para->video_codec_id)
1147 || (AV_CODEC_ID_MPEG2VIDEO_XVMC == para->video_codec_id)) {
1148 ret = mpeg_add_header(para, pkt);
1149 if (ret != PLAYER_SUCCESS) {
1154 if (pkt->hdr->data) {
1155 free(pkt->hdr->data);
1156 pkt->hdr->data = NULL;
1162 return PLAYER_SUCCESS;
1165 int divx3_prefix(am_packet_t *pkt)
1167 #define DIVX311_CHUNK_HEAD_SIZE 13
1168 const unsigned char divx311_chunk_prefix[DIVX311_CHUNK_HEAD_SIZE] = {
1169 0x00, 0x00, 0x00, 0x01, 0xb6, 'D', 'I', 'V', 'X', '3', '.', '1', '1'
1171 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1172 free(pkt->hdr->data);
1173 pkt->hdr->data = NULL;
1176 if (pkt->hdr == NULL) {
1177 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1179 CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1180 return PLAYER_FAILED;
1183 pkt->hdr->data = NULL;
1187 pkt->hdr->data = (char*)malloc(DIVX311_CHUNK_HEAD_SIZE + 4);
1188 if (pkt->hdr->data == NULL) {
1189 CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!");
1190 return PLAYER_FAILED;
1193 memcpy(pkt->hdr->data, divx311_chunk_prefix, DIVX311_CHUNK_HEAD_SIZE);
1195 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 0] = (pkt->data_size >> 24) & 0xff;
1196 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 1] = (pkt->data_size >> 16) & 0xff;
1197 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 2] = (pkt->data_size >> 8) & 0xff;
1198 pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 3] = pkt->data_size & 0xff;
1200 pkt->hdr->size = DIVX311_CHUNK_HEAD_SIZE + 4;
1203 return PLAYER_SUCCESS;
1206 int set_header_info(am_private_t *para)
1208 am_packet_t *pkt = ¶->am_pkt;
1213 // pkt->hdr->size = 0;
1215 if (para->video_format == VFORMAT_MPEG4)
1217 if (para->video_codec_type == VIDEO_DEC_FORMAT_MPEG4_3)
1219 return divx3_prefix(pkt);
1221 else if (para->video_codec_type == VIDEO_DEC_FORMAT_H263)
1223 return PLAYER_UNSUPPORT;
1224 unsigned char *vld_buf;
1225 int vld_len, vld_buf_size = para->video_width * para->video_height * 2;
1227 if (!pkt->data_size) {
1228 return PLAYER_SUCCESS;
1231 if ((pkt->data[0] == 0) && (pkt->data[1] == 0) && (pkt->data[2] == 1) && (pkt->data[3] == 0xb6)) {
1232 return PLAYER_SUCCESS;
1235 vld_buf = (unsigned char*)malloc(vld_buf_size);
1237 return PLAYER_NOMEM;
1240 if (para->flv_flag) {
1241 vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 1);
1243 if (0 == para->h263_decodable) {
1244 para->h263_decodable = para->m_dll->decodeble_h263(pkt->data);
1245 if (0 == para->h263_decodable) {
1246 CLog::Log(LOGDEBUG, "[%s]h263 unsupport video and audio, exit", __FUNCTION__);
1247 return PLAYER_UNSUPPORT;
1250 vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 0);
1258 pkt->buf_size = vld_buf_size;
1259 pkt->data = pkt->buf;
1260 pkt->data_size = vld_len;
1266 } else if (para->video_format == VFORMAT_VC1) {
1267 if (para->video_codec_type == VIDEO_DEC_FORMAT_WMV3) {
1268 unsigned i, check_sum = 0, data_len = 0;
1270 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1271 free(pkt->hdr->data);
1272 pkt->hdr->data = NULL;
1275 if (pkt->hdr == NULL) {
1276 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1278 return PLAYER_FAILED;
1281 pkt->hdr->data = NULL;
1285 if (pkt->avpkt.flags) {
1286 pkt->hdr->data = (char*)malloc(para->extrasize + 26 + 22);
1287 if (pkt->hdr->data == NULL) {
1288 return PLAYER_FAILED;
1291 pkt->hdr->data[0] = 0;
1292 pkt->hdr->data[1] = 0;
1293 pkt->hdr->data[2] = 1;
1294 pkt->hdr->data[3] = 0x10;
1296 data_len = para->extrasize + 4;
1297 pkt->hdr->data[4] = 0;
1298 pkt->hdr->data[5] = (data_len >> 16) & 0xff;
1299 pkt->hdr->data[6] = 0x88;
1300 pkt->hdr->data[7] = (data_len >> 8) & 0xff;
1301 pkt->hdr->data[8] = data_len & 0xff;
1302 pkt->hdr->data[9] = 0x88;
1304 pkt->hdr->data[10] = 0xff;
1305 pkt->hdr->data[11] = 0xff;
1306 pkt->hdr->data[12] = 0x88;
1307 pkt->hdr->data[13] = 0xff;
1308 pkt->hdr->data[14] = 0xff;
1309 pkt->hdr->data[15] = 0x88;
1311 for (i = 4 ; i < 16 ; i++) {
1312 check_sum += pkt->hdr->data[i];
1315 pkt->hdr->data[16] = (check_sum >> 8) & 0xff;
1316 pkt->hdr->data[17] = check_sum & 0xff;
1317 pkt->hdr->data[18] = 0x88;
1318 pkt->hdr->data[19] = (check_sum >> 8) & 0xff;
1319 pkt->hdr->data[20] = check_sum & 0xff;
1320 pkt->hdr->data[21] = 0x88;
1322 pkt->hdr->data[22] = (para->video_width >> 8) & 0xff;
1323 pkt->hdr->data[23] = para->video_width & 0xff;
1324 pkt->hdr->data[24] = (para->video_height >> 8) & 0xff;
1325 pkt->hdr->data[25] = para->video_height & 0xff;
1327 memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize);
1330 data_len = para->extrasize + 26;
1332 pkt->hdr->data = (char*)malloc(22);
1333 if (pkt->hdr->data == NULL) {
1334 return PLAYER_FAILED;
1338 pkt->hdr->data[data_len + 0] = 0;
1339 pkt->hdr->data[data_len + 1] = 0;
1340 pkt->hdr->data[data_len + 2] = 1;
1341 pkt->hdr->data[data_len + 3] = 0xd;
1343 pkt->hdr->data[data_len + 4] = 0;
1344 pkt->hdr->data[data_len + 5] = (pkt->data_size >> 16) & 0xff;
1345 pkt->hdr->data[data_len + 6] = 0x88;
1346 pkt->hdr->data[data_len + 7] = (pkt->data_size >> 8) & 0xff;
1347 pkt->hdr->data[data_len + 8] = pkt->data_size & 0xff;
1348 pkt->hdr->data[data_len + 9] = 0x88;
1350 pkt->hdr->data[data_len + 10] = 0xff;
1351 pkt->hdr->data[data_len + 11] = 0xff;
1352 pkt->hdr->data[data_len + 12] = 0x88;
1353 pkt->hdr->data[data_len + 13] = 0xff;
1354 pkt->hdr->data[data_len + 14] = 0xff;
1355 pkt->hdr->data[data_len + 15] = 0x88;
1357 for (i = data_len + 4 ; i < data_len + 16 ; i++) {
1358 check_sum += pkt->hdr->data[i];
1361 pkt->hdr->data[data_len + 16] = (check_sum >> 8) & 0xff;
1362 pkt->hdr->data[data_len + 17] = check_sum & 0xff;
1363 pkt->hdr->data[data_len + 18] = 0x88;
1364 pkt->hdr->data[data_len + 19] = (check_sum >> 8) & 0xff;
1365 pkt->hdr->data[data_len + 20] = check_sum & 0xff;
1366 pkt->hdr->data[data_len + 21] = 0x88;
1368 pkt->hdr->size = data_len + 22;
1370 } else if (para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) {
1371 if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) {
1372 free(pkt->hdr->data);
1373 pkt->hdr->data = NULL;
1376 if (pkt->hdr == NULL) {
1377 pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t));
1379 CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1380 return PLAYER_FAILED;
1383 pkt->hdr->data = NULL;
1387 pkt->hdr->data = (char*)malloc(4);
1388 if (pkt->hdr->data == NULL) {
1389 CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!");
1390 return PLAYER_FAILED;
1393 pkt->hdr->data[0] = 0;
1394 pkt->hdr->data[1] = 0;
1395 pkt->hdr->data[2] = 1;
1396 pkt->hdr->data[3] = 0xd;
1402 return PLAYER_SUCCESS;
1405 /*************************************************************************/
1406 CAMLCodec::CAMLCodec() : CThread("CAMLCodec")
1409 am_private = new am_private_t;
1410 memset(am_private, 0, sizeof(am_private_t));
1411 m_dll = new DllLibAmCodec;
1413 am_private->m_dll = m_dll;
1417 CAMLCodec::~CAMLCodec()
1422 delete m_dll, m_dll = NULL;
1425 bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
1427 #ifdef TARGET_ANDROID
1428 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder, android version %d", CAndroidFeatures::GetVersion());
1431 m_speed = DVD_PLAYSPEED_NORMAL;
1436 m_dst_rect.SetRect(0, 0, 0, 0);
1440 m_vbufsize = 500000 * 2;
1445 ShowMainVideo(false);
1447 am_packet_init(&am_private->am_pkt);
1448 // default stream type
1449 am_private->stream_type = AM_STREAM_ES;
1451 am_private->video_width = hints.width;
1452 am_private->video_height = hints.height;
1453 am_private->video_codec_id = hints.codec;
1454 am_private->video_codec_tag = hints.codec_tag;
1455 am_private->video_pid = hints.pid;
1457 // handle video ratio
1458 AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX);
1459 //if (!hints.forced_aspect)
1460 // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX);
1461 am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den;
1462 am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den;
1464 // handle video rate
1465 if (hints.rfpsrate > 0 && hints.rfpsscale != 0)
1467 // check ffmpeg r_frame_rate 1st
1468 am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate;
1470 else if (hints.fpsrate > 0 && hints.fpsscale != 0)
1472 // then ffmpeg avg_frame_rate next
1473 am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate;
1476 // check for 1920x1080, interlaced, 25 fps
1477 // incorrectly reported as 50 fps (yes, video_rate == 1920)
1478 if (hints.width == 1920 && am_private->video_rate == 1920)
1480 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1481 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000;
1484 // check for SD h264 content incorrectly reported as 60 fsp
1485 // mp4/avi containers :(
1486 if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 1602)
1488 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1489 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1492 // check for SD h264 content incorrectly reported as some form of 30 fsp
1493 // mp4/avi containers :(
1494 if (hints.codec == AV_CODEC_ID_H264 && hints.width <= 720)
1496 if (am_private->video_rate >= 3200 && am_private->video_rate <= 3210)
1498 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception");
1499 am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000;
1503 // handle orientation
1504 am_private->video_rotation_degree = 0;
1505 if (hints.orientation == 90)
1506 am_private->video_rotation_degree = 1;
1507 else if (hints.orientation == 180)
1508 am_private->video_rotation_degree = 2;
1509 else if (hints.orientation == 270)
1510 am_private->video_rotation_degree = 3;
1512 am_private->video_format = codecid_to_vformat(hints.codec);
1513 switch (am_private->video_format)
1516 am_private->extrasize = hints.extrasize;
1517 am_private->extradata = (uint8_t*)malloc(hints.extrasize);
1518 memcpy(am_private->extradata, hints.extradata, hints.extrasize);
1521 case VFORMAT_MPEG12:
1525 if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0)
1526 am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag);
1528 am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id);
1530 am_private->flv_flag = 0;
1531 if (am_private->video_codec_id == AV_CODEC_ID_FLV1)
1533 am_private->video_codec_tag = CODEC_TAG_F263;
1534 am_private->flv_flag = 1;
1537 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder "
1538 "hints.width(%d), hints.height(%d), hints.codec(%d), hints.codec_tag(%d), hints.pid(%d)",
1539 hints.width, hints.height, hints.codec, hints.codec_tag, hints.pid);
1540 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)",
1541 hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate);
1542 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)",
1543 hints.aspect, video_ratio.num, video_ratio.den);
1544 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)",
1545 hints.orientation, hints.forced_aspect, hints.extrasize);
1547 // default video codec params
1548 am_private->gcodec.noblock = 0;
1549 am_private->gcodec.video_pid = am_private->video_pid;
1550 am_private->gcodec.video_type = am_private->video_format;
1551 am_private->gcodec.stream_type = STREAM_TYPE_ES_VIDEO;
1552 am_private->gcodec.format = am_private->video_codec_type;
1553 am_private->gcodec.width = am_private->video_width;
1554 am_private->gcodec.height = am_private->video_height;
1555 am_private->gcodec.rate = am_private->video_rate;
1556 am_private->gcodec.ratio = am_private->video_ratio;
1557 am_private->gcodec.ratio64 = am_private->video_ratio64;
1558 am_private->gcodec.param = NULL;
1560 switch(am_private->video_format)
1565 am_private->gcodec.param = (void*)EXTERNAL_PTS;
1568 case VFORMAT_H264MVC:
1569 am_private->gcodec.format = VIDEO_DEC_FORMAT_H264;
1570 am_private->gcodec.param = (void*)EXTERNAL_PTS;
1571 // h264 in an avi file
1572 if (m_hints.ptsinvalid)
1573 am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
1576 am_private->stream_type = AM_STREAM_RM;
1577 am_private->vcodec.noblock = 1;
1578 am_private->vcodec.stream_type = STREAM_TYPE_RM;
1579 am_private->vcodec.am_sysinfo.ratio = 0x100;
1580 am_private->vcodec.am_sysinfo.ratio64 = 0;
1582 static unsigned short tbl[9] = {0};
1583 if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type)
1585 am_private->gcodec.extra = am_private->extradata[1] & 7;
1586 tbl[0] = (((am_private->gcodec.width >> 2) - 1) << 8)
1587 | (((am_private->gcodec.height >> 2) - 1) & 0xff);
1589 for (unsigned int i = 1; i <= am_private->gcodec.extra; i++)
1592 tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff);
1595 am_private->gcodec.param = &tbl;
1599 // vc1 in an avi file
1600 if (m_hints.ptsinvalid)
1601 am_private->gcodec.param = (void*)EXTERNAL_PTS;
1604 am_private->gcodec.param = (void *)((unsigned int)am_private->gcodec.param | (am_private->video_rotation_degree << 16));
1606 // translate from generic to firemware version dependent
1607 m_dll->codec_init_para(&am_private->gcodec, &am_private->vcodec);
1609 int ret = m_dll->codec_init(&am_private->vcodec);
1610 if (ret != CODEC_ERROR_NONE)
1612 CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret);
1615 am_private->dumpdemux = false;
1616 dumpfile_open(am_private);
1618 // make sure we are not stuck in pause (amcodec bug)
1619 m_dll->codec_resume(&am_private->vcodec);
1620 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1622 m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH);
1623 m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0);
1624 // disable tsync, we are playing video disconnected from audio.
1625 aml_set_sysfs_int("/sys/class/tsync/enable", 0);
1627 am_private->am_pkt.codec = &am_private->vcodec;
1628 pre_header_feeding(am_private, &am_private->am_pkt);
1632 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1633 g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack);
1636 // if display is set to 1080xxx, then disable deinterlacer for HD content
1637 // else bandwidth usage is too heavy and it will slow down video decoder.
1638 char display_mode[256] = {0};
1639 aml_get_sysfs_str("/sys/class/display/mode", display_mode, 255);
1640 if (strstr(display_mode,"1080"))
1641 aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 1);
1643 aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 0);
1647 // vcodec is open, update speed if it was
1648 // changed before dvdplayer called OpenDecoder.
1654 void CAMLCodec::CloseDecoder()
1656 CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder");
1659 g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL);
1660 g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL);
1662 // never leave vcodec ff/rw or paused.
1663 if (m_speed != DVD_PLAYSPEED_NORMAL)
1665 m_dll->codec_resume(&am_private->vcodec);
1666 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1668 m_dll->codec_close(&am_private->vcodec);
1669 dumpfile_close(am_private);
1672 am_packet_release(&am_private->am_pkt);
1673 free(am_private->extradata);
1674 am_private->extradata = NULL;
1675 // return tsync to default so external apps work
1676 aml_set_sysfs_int("/sys/class/tsync/enable", 1);
1678 ShowMainVideo(false);
1681 void CAMLCodec::Reset()
1683 CLog::Log(LOGDEBUG, "CAMLCodec::Reset");
1688 // set the system blackout_policy to leave the last frame showing
1689 int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy");
1690 aml_set_sysfs_int("/sys/class/video/blackout_policy", 0);
1692 // restore the speed (some amcodec versions require this)
1693 if (m_speed != DVD_PLAYSPEED_NORMAL)
1695 m_dll->codec_resume(&am_private->vcodec);
1696 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1698 // reset the decoder
1699 m_dll->codec_reset(&am_private->vcodec);
1700 dumpfile_close(am_private);
1701 dumpfile_open(am_private);
1703 // re-init our am_pkt
1704 am_packet_release(&am_private->am_pkt);
1705 am_packet_init(&am_private->am_pkt);
1706 am_private->am_pkt.codec = &am_private->vcodec;
1707 pre_header_feeding(am_private, &am_private->am_pkt);
1709 // restore the saved system blackout_policy value
1710 aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy);
1712 // reset some interal vars
1720 int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
1725 // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during
1726 // g_renderManager.Configure call by player, which happens after the codec
1727 // OpenDecoder call. So we need to restore it but it does not seem to stick :)
1728 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
1732 am_private->am_pkt.data = pData;
1733 am_private->am_pkt.data_size = iSize;
1735 am_private->am_pkt.newflag = 1;
1736 am_private->am_pkt.isvalid = 1;
1737 am_private->am_pkt.avduration = 0;
1739 // handle pts, including 31bit wrap, aml can only handle 31
1740 // bit pts as it uses an int in kernel.
1741 if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE)
1742 am_private->am_pkt.avpts = AV_NOPTS_VALUE;
1745 am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\
1746 if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff)
1747 m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff;
1749 if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE)
1750 am_private->am_pkt.avpts -= m_start_pts;
1753 // handle dts, including 31bit wrap, aml can only handle 31
1754 // bit dts as it uses an int in kernel.
1755 if (dts == DVD_NOPTS_VALUE)
1756 am_private->am_pkt.avdts = AV_NOPTS_VALUE;
1759 am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE;
1760 if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff)
1761 m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff;
1763 if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE)
1764 am_private->am_pkt.avdts -= m_start_dts;
1766 //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)",
1767 // iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts);
1769 // some formats need header/data tweaks.
1770 // the actual write occurs once in write_av_packet
1771 // and is controlled by am_pkt.newflag.
1772 set_header_info(am_private);
1774 // loop until we write all into codec, am_pkt.isvalid
1775 // will get set to zero once everything is consumed.
1776 // PLAYER_SUCCESS means all is ok, not all bytes were written.
1777 while (am_private->am_pkt.isvalid)
1779 // abort on any errors.
1780 if (write_av_packet(am_private, &am_private->am_pkt) != PLAYER_SUCCESS)
1783 if (am_private->am_pkt.isvalid)
1784 CLog::Log(LOGDEBUG, "CAMLCodec::Decode: write_av_packet looping");
1787 // if we seek, then GetTimeSize is wrong as
1788 // reports lastpts - cur_pts and hw decoder has
1789 // not started outputing new pts values yet.
1790 // so we grab the 1st pts sent into driver and
1791 // use that to calc GetTimeSize.
1793 m_1st_pts = am_private->am_pkt.lastpts;
1796 // if we have still frames, demux size will be small
1797 // and we need to pre-buffer more.
1798 double target_timesize = 1.0;
1800 target_timesize = 2.0;
1802 // keep hw buffered demux above 1 second
1803 if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL)
1806 // wait until we get a new frame or 25ms,
1807 if (m_old_pictcnt == m_cur_pictcnt)
1808 m_ready_event.WaitMSec(25);
1810 // we must return VC_BUFFER or VC_PICTURE,
1811 // default to VC_BUFFER.
1812 int rtn = VC_BUFFER;
1813 if (m_old_pictcnt != m_cur_pictcnt)
1817 // we got a new pict, try and keep hw buffered demux above 2 seconds.
1818 // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds.
1819 // we also check to make sure we keep from filling hw buffer.
1820 if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3)
1824 CLog::Log(LOGDEBUG, "CAMLCodec::Decode: "
1825 "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)",
1826 rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize());
1831 bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture)
1836 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
1837 pDvdVideoPicture->format = RENDER_FMT_BYPASS;
1838 pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
1840 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
1841 pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE;
1842 // video pts cannot be late or dvdplayer goes nuts,
1843 // so run it one frame ahead
1844 pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration;
1849 void CAMLCodec::SetSpeed(int speed)
1851 CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed);
1853 // update internal vars regardless
1854 // of if we are open or not.
1862 case DVD_PLAYSPEED_PAUSE:
1863 m_dll->codec_pause(&am_private->vcodec);
1864 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1866 case DVD_PLAYSPEED_NORMAL:
1867 m_dll->codec_resume(&am_private->vcodec);
1868 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
1871 m_dll->codec_resume(&am_private->vcodec);
1872 if (am_private->video_format == VFORMAT_H264)
1873 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB);
1875 m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I);
1880 int CAMLCodec::GetDataSize()
1885 struct buf_status vbuf ={0};
1886 if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0)
1887 m_vbufsize = vbuf.size;
1889 return vbuf.data_len;
1892 double CAMLCodec::GetTimeSize()
1897 // if m_cur_pts is zero, hw decoder was not started yet
1898 // so we use the pts of the 1st demux packet that was send
1899 // to hw decoder to calc timesize.
1901 m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ;
1903 m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ;
1905 // lie to DVDPlayer, it is hardcoded to a max of 8 seconds,
1906 // if you buffer more than 8 seconds, it goes nuts.
1907 double timesize = m_timesize;
1910 else if (timesize > 7.0)
1916 void CAMLCodec::Process()
1918 CLog::Log(LOGDEBUG, "CAMLCodec::Process Started");
1920 // bump our priority to be level with SoftAE
1921 SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
1924 int64_t pts_video = 0;
1925 if (am_private->am_pkt.lastpts > 0)
1927 // this is a blocking poll that returns every vsync.
1928 // since we are running at a higher priority, make sure
1929 // we sleep if the call fails or does a timeout.
1930 if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0)
1932 CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed");
1936 pts_video = get_pts_video();
1937 if (m_cur_pts != pts_video)
1939 //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)",
1940 // pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ));
1942 // other threads look at these, do them first
1943 m_cur_pts = pts_video;
1945 m_ready_event.Set();
1947 // correct video pts by starting pts.
1948 if (m_start_pts != 0)
1949 pts_video += m_start_pts;
1950 else if (m_start_dts != 0)
1951 pts_video += m_start_dts;
1953 double app_pts = GetPlayerPtsSeconds();
1954 // add in audio delay/display latency contribution
1955 double offset = g_renderManager.GetDisplayLatency() - CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay;
1956 // correct video pts by user set delay and rendering delay
1959 //CLog::Log(LOGDEBUG, "CAMLCodec::Process: app_pts(%f), pts_video/PTS_FREQ(%f)",
1960 // app_pts, (double)pts_video/PTS_FREQ);
1962 double error = app_pts - (double)pts_video/PTS_FREQ;
1963 double abs_error = fabs(error);
1964 if (abs_error > 0.125)
1966 //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error);
1967 if (abs_error > 0.150)
1969 // big error so try to reset pts_pcrscr
1970 SetVideoPtsSeconds(app_pts);
1974 // small error so try to avoid a frame jump
1975 SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4);
1985 SetPriority(THREAD_PRIORITY_NORMAL);
1986 CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped");
1989 double CAMLCodec::GetPlayerPtsSeconds()
1991 double clock_pts = 0.0;
1992 CDVDClock *playerclock = CDVDClock::GetMasterClock();
1994 clock_pts = playerclock->GetClock() / DVD_TIME_BASE;
1999 void CAMLCodec::SetVideoPtsSeconds(const double pts)
2001 //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts);
2004 int64_t pts_video = (int64_t)(pts * PTS_FREQ);
2005 if (m_start_pts != 0)
2006 pts_video -= m_start_pts;
2007 else if (m_start_dts != 0)
2008 pts_video -= m_start_dts;
2010 set_pts_pcrscr(pts_video);
2014 void CAMLCodec::ShowMainVideo(const bool show)
2016 static int saved_disable_video = -1;
2018 int disable_video = show ? 0:1;
2019 if (saved_disable_video == disable_video)
2022 aml_set_sysfs_int("/sys/class/video/disable_video", disable_video);
2023 saved_disable_video = disable_video;
2026 void CAMLCodec::SetVideoZoom(const float zoom)
2028 // input zoom range is 0.5 to 2.0 with a default of 1.0.
2029 // output zoom range is 2 to 300 with default of 100.
2030 // we limit that to a range of 50 to 200 with default of 100.
2031 aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom));
2034 void CAMLCodec::SetVideoContrast(const int contrast)
2036 // input contrast range is 0 to 100 with default of 50.
2037 // output contrast range is -255 to 255 with default of 0.
2038 int aml_contrast = (255 * (contrast - 50)) / 50;
2039 aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast);
2041 void CAMLCodec::SetVideoBrightness(const int brightness)
2043 // input brightness range is 0 to 100 with default of 50.
2044 // output brightness range is -127 to 127 with default of 0.
2045 int aml_brightness = (127 * (brightness - 50)) / 50;
2046 aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness);
2048 void CAMLCodec::SetVideoSaturation(const int saturation)
2050 // output saturation range is -127 to 127 with default of 127.
2051 aml_set_sysfs_int("/sys/class/video/saturation", saturation);
2054 void CAMLCodec::GetRenderFeatures(Features &renderFeatures)
2056 renderFeatures.push_back(RENDERFEATURE_ZOOM);
2057 renderFeatures.push_back(RENDERFEATURE_CONTRAST);
2058 renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS);
2059 renderFeatures.push_back(RENDERFEATURE_STRETCH);
2060 renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO);
2064 void CAMLCodec::SetVideo3dMode(const int mode3d)
2066 aml_set_sysfs_int("/sys/class/ppmgr/ppmgr_3d_mode", mode3d);
2069 std::string CAMLCodec::GetStereoMode()
2071 std::string stereo_mode;
2073 switch(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode)
2075 case RENDER_STEREO_MODE_SPLIT_VERTICAL: stereo_mode = "left_right"; break;
2076 case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: stereo_mode = "top_bottom"; break;
2077 default: stereo_mode = m_hints.stereo_mode; break;
2080 if(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert)
2081 stereo_mode = RenderManager::GetStereoModeInvert(stereo_mode);
2085 void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures)
2087 CAMLCodec *codec = (CAMLCodec*)ctx;
2089 codec->GetRenderFeatures(renderFeatures);
2092 void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
2094 // this routine gets called every video frame
2095 // and is in the context of the renderer thread so
2096 // do not do anything stupid here.
2097 bool update = false;
2099 // video zoom adjustment.
2100 float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount;
2101 if ((int)(zoom * 1000) != (int)(m_zoom * 1000))
2105 // video contrast adjustment.
2106 int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast;
2107 if (contrast != m_contrast)
2109 SetVideoContrast(contrast);
2110 m_contrast = contrast;
2112 // video brightness adjustment.
2113 int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness;
2114 if (brightness != m_brightness)
2116 SetVideoBrightness(brightness);
2117 m_brightness = brightness;
2121 int view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
2122 if (m_view_mode != view_mode)
2124 m_view_mode = view_mode;
2128 // video stereo mode/view.
2129 RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
2130 if (m_stereo_mode != stereo_mode)
2132 m_stereo_mode = stereo_mode;
2135 RENDER_STEREO_VIEW stereo_view = g_graphicsContext.GetStereoView();
2136 if (m_stereo_view != stereo_view)
2138 // left/right/top/bottom eye,
2139 // this might change every other frame.
2140 // we do not care but just track it.
2141 m_stereo_view = stereo_view;
2145 if (m_dst_rect != DestRect)
2147 m_dst_rect = DestRect;
2153 // mainvideo 'should' be showing already if we get here, make sure.
2154 ShowMainVideo(true);
2158 CRect gui, display, dst_rect;
2159 gui = g_graphicsContext.GetViewWindow();
2160 // when display is at 1080p, we have freescale enabled
2161 // and that scales all layers into 1080p display including video,
2162 // so we have to setup video axis for 720p instead of 1080p... Boooo.
2163 display = g_graphicsContext.GetViewWindow();
2164 dst_rect = m_dst_rect;
2167 float xscale = display.Width() / gui.Width();
2168 float yscale = display.Height() / gui.Height();
2169 dst_rect.x1 *= xscale;
2170 dst_rect.x2 *= xscale;
2171 dst_rect.y1 *= yscale;
2172 dst_rect.y2 *= yscale;
2176 std::string rectangle = StringUtils::Format("%i,%i,%i,%i",
2177 (int)dst_rect.x1, (int)dst_rect.y1,
2178 (int)dst_rect.Width(), (int)dst_rect.Height());
2179 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str());
2180 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_mode(%d)", m_stereo_mode);
2181 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_stereo_view(%d)", m_stereo_view);
2184 if (m_stereo_mode == RENDER_STEREO_MODE_MONO)
2186 std::string mode = GetStereoMode();
2187 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:mode(%s)", mode.c_str());
2188 if (mode == "left_right")
2189 SetVideo3dMode(MODE_3D_TO_2D_L);
2190 else if (mode == "right_left")
2191 SetVideo3dMode(MODE_3D_TO_2D_R);
2192 else if (mode == "top_bottom")
2193 SetVideo3dMode(MODE_3D_TO_2D_T);
2194 else if (mode == "bottom_top")
2195 SetVideo3dMode(MODE_3D_TO_2D_B);
2197 SetVideo3dMode(MODE_3D_DISABLE);
2199 else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
2202 //SetVideo3dMode(MODE_3D_LR);
2203 SetVideo3dMode(MODE_3D_DISABLE);
2205 else if (m_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
2208 //SetVideo3dMode(MODE_3D_BT);
2209 SetVideo3dMode(MODE_3D_DISABLE);
2213 SetVideo3dMode(MODE_3D_DISABLE);
2216 // goofy 0/1 based difference in aml axis coordinates.
2221 char video_axis[256] = {};
2222 sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2);
2224 aml_set_sysfs_str("/sys/class/video/axis", video_axis);
2225 // make sure we are in 'full stretch' so we can stretch
2226 aml_set_sysfs_int("/sys/class/video/screen_mode", 1);
2228 // we only get called once gui has changed to something
2229 // that would show video playback, so show it.
2230 ShowMainVideo(true);
2233 void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
2235 CAMLCodec *codec = (CAMLCodec*)ctx;
2236 codec->SetVideoRect(SrcRect, DestRect);