From cd783bd89b7da4e7b13cb0c1fea20fe57c273cd7 Mon Sep 17 00:00:00 2001 From: max_10 Date: Sat, 16 Dec 2017 23:41:01 +0100 Subject: [PATCH] add libeplayer3-arm test Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/d2b5eae8f74da12813ec7d82b936de5c3bd84c92 Author: max_10 Date: 2017-12-16 (Sat, 16 Dec 2017) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- Makefile.am | 8 + configure.ac | 33 +- include/playback_hal.h | 4 + libarmbox/Makefile.am | 25 +- libarmbox/playback_libeplayer3.cpp | 703 +++ libarmbox/playback_libeplayer3.h | 91 + libeplayer3-arm/Makefile.am | 49 + libeplayer3-arm/README.md | 2 + libeplayer3-arm/container/buff_ffmpeg.c | 601 +++ libeplayer3-arm/container/container.c | 137 + libeplayer3-arm/container/container_ffmpeg.c | 2684 +++++++++++ libeplayer3-arm/container/flv2mpeg4_ffmpeg.c | 85 + libeplayer3-arm/container/mpeg4p2_ffmpeg.c | 210 + libeplayer3-arm/container/wrapped_ffmpeg.c | 184 + libeplayer3-arm/external/ffmpeg/get_bits.h | 544 +++ libeplayer3-arm/external/ffmpeg/latmenc.h | 45 + libeplayer3-arm/external/ffmpeg/mathops.h | 56 + libeplayer3-arm/external/ffmpeg/mpeg4audio.h | 112 + libeplayer3-arm/external/ffmpeg/put_bits.h | 274 ++ .../external/ffmpeg/src/bitstream.c | 75 + libeplayer3-arm/external/ffmpeg/src/latmenc.c | 155 + .../external/ffmpeg/src/mpeg4audio.c | 190 + .../external/flv2mpeg4/doc/COPYING | 504 +++ .../external/flv2mpeg4/doc/CREDITS | 5 + .../external/flv2mpeg4/doc/FFMPEG_CREDITS | 46 + .../external/flv2mpeg4/doc/FFMPEG_IMPORTS | 32 + .../external/flv2mpeg4/doc/INSTALL | 14 + libeplayer3-arm/external/flv2mpeg4/doc/README | 16 + .../external/flv2mpeg4/flv2mpeg4.h | 45 + .../external/flv2mpeg4/src/bitreader.h | 177 + .../external/flv2mpeg4/src/bitwriter.h | 144 + .../external/flv2mpeg4/src/dcprediction.c | 183 + .../external/flv2mpeg4/src/dcprediction.h | 56 + libeplayer3-arm/external/flv2mpeg4/src/flv.h | 161 + .../external/flv2mpeg4/src/flv2mpeg4.c | 289 ++ .../external/flv2mpeg4/src/flvdecoder.c | 523 +++ libeplayer3-arm/external/flv2mpeg4/src/m4v.h | 139 + .../external/flv2mpeg4/src/m4vencode.c | 603 +++ .../external/flv2mpeg4/src/m4vencode.h | 37 + .../external/flv2mpeg4/src/m4vencode_tables.h | 3993 +++++++++++++++++ libeplayer3-arm/external/flv2mpeg4/src/type.h | 46 + libeplayer3-arm/include/aac.h | 67 + libeplayer3-arm/include/bcm_ioctls.h | 85 + libeplayer3-arm/include/common.h | 29 + libeplayer3-arm/include/container.h | 48 + libeplayer3-arm/include/debug.h | 19 + libeplayer3-arm/include/ffmpeg_metadata.h | 45 + libeplayer3-arm/include/manager.h | 109 + libeplayer3-arm/include/misc.h | 112 + libeplayer3-arm/include/output.h | 88 + libeplayer3-arm/include/pcm.h | 36 + libeplayer3-arm/include/pes.h | 32 + libeplayer3-arm/include/playback.h | 41 + libeplayer3-arm/include/stm_ioctls.h | 335 ++ libeplayer3-arm/include/writer.h | 92 + libeplayer3-arm/main/exteplayer.c | 843 ++++ libeplayer3-arm/manager/audio.c | 323 ++ libeplayer3-arm/manager/manager.c | 116 + libeplayer3-arm/manager/subtitle.c | 335 ++ libeplayer3-arm/manager/video.c | 336 ++ libeplayer3-arm/output/linuxdvb_mipsel.c | 1118 +++++ libeplayer3-arm/output/linuxdvb_sh4.c | 1122 +++++ libeplayer3-arm/output/output.c | 560 +++ libeplayer3-arm/output/output_subtitle.c | 332 ++ libeplayer3-arm/output/writer/common/misc.c | 123 + libeplayer3-arm/output/writer/common/pes.c | 163 + libeplayer3-arm/output/writer/mipsel/aac.c | 374 ++ libeplayer3-arm/output/writer/mipsel/ac3.c | 170 + libeplayer3-arm/output/writer/mipsel/amr.c | 176 + libeplayer3-arm/output/writer/mipsel/divx3.c | 196 + libeplayer3-arm/output/writer/mipsel/dts.c | 178 + libeplayer3-arm/output/writer/mipsel/h263.c | 171 + libeplayer3-arm/output/writer/mipsel/h264.c | 441 ++ libeplayer3-arm/output/writer/mipsel/h265.c | 310 ++ libeplayer3-arm/output/writer/mipsel/lpcm.c | 266 ++ libeplayer3-arm/output/writer/mipsel/mp3.c | 189 + libeplayer3-arm/output/writer/mipsel/mpeg2.c | 180 + libeplayer3-arm/output/writer/mipsel/mpeg4.c | 164 + libeplayer3-arm/output/writer/mipsel/pcm.c | 312 ++ libeplayer3-arm/output/writer/mipsel/vc1.c | 200 + libeplayer3-arm/output/writer/mipsel/vp.c | 228 + libeplayer3-arm/output/writer/mipsel/wma.c | 202 + libeplayer3-arm/output/writer/mipsel/wmv.c | 206 + libeplayer3-arm/output/writer/mipsel/writer.c | 204 + libeplayer3-arm/output/writer/sh4/aac.c | 372 ++ libeplayer3-arm/output/writer/sh4/ac3.c | 165 + libeplayer3-arm/output/writer/sh4/divx.c | 237 + libeplayer3-arm/output/writer/sh4/divx2.c | 263 ++ libeplayer3-arm/output/writer/sh4/dts.c | 176 + libeplayer3-arm/output/writer/sh4/h263.c | 173 + libeplayer3-arm/output/writer/sh4/h264.c | 480 ++ libeplayer3-arm/output/writer/sh4/mp3.c | 178 + libeplayer3-arm/output/writer/sh4/mpeg2.c | 181 + libeplayer3-arm/output/writer/sh4/pcm.c | 354 ++ libeplayer3-arm/output/writer/sh4/pes.c | 154 + libeplayer3-arm/output/writer/sh4/vc1.c | 263 ++ libeplayer3-arm/output/writer/sh4/vorbis.c | 146 + libeplayer3-arm/output/writer/sh4/wma.c | 191 + libeplayer3-arm/output/writer/sh4/wmv.c | 254 ++ libeplayer3-arm/output/writer/sh4/writer.c | 144 + libeplayer3-arm/playback/playback.c | 700 +++ 101 files changed, 28366 insertions(+), 21 deletions(-) create mode 100644 libarmbox/playback_libeplayer3.cpp create mode 100644 libarmbox/playback_libeplayer3.h create mode 100644 libeplayer3-arm/Makefile.am create mode 100644 libeplayer3-arm/README.md create mode 100644 libeplayer3-arm/container/buff_ffmpeg.c create mode 100644 libeplayer3-arm/container/container.c create mode 100644 libeplayer3-arm/container/container_ffmpeg.c create mode 100644 libeplayer3-arm/container/flv2mpeg4_ffmpeg.c create mode 100644 libeplayer3-arm/container/mpeg4p2_ffmpeg.c create mode 100644 libeplayer3-arm/container/wrapped_ffmpeg.c create mode 100644 libeplayer3-arm/external/ffmpeg/get_bits.h create mode 100644 libeplayer3-arm/external/ffmpeg/latmenc.h create mode 100644 libeplayer3-arm/external/ffmpeg/mathops.h create mode 100644 libeplayer3-arm/external/ffmpeg/mpeg4audio.h create mode 100644 libeplayer3-arm/external/ffmpeg/put_bits.h create mode 100644 libeplayer3-arm/external/ffmpeg/src/bitstream.c create mode 100644 libeplayer3-arm/external/ffmpeg/src/latmenc.c create mode 100644 libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/COPYING create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/CREDITS create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_CREDITS create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_IMPORTS create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/INSTALL create mode 100644 libeplayer3-arm/external/flv2mpeg4/doc/README create mode 100644 libeplayer3-arm/external/flv2mpeg4/flv2mpeg4.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/bitreader.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/flv.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/m4v.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/m4vencode.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/m4vencode_tables.h create mode 100644 libeplayer3-arm/external/flv2mpeg4/src/type.h create mode 100644 libeplayer3-arm/include/aac.h create mode 100644 libeplayer3-arm/include/bcm_ioctls.h create mode 100644 libeplayer3-arm/include/common.h create mode 100644 libeplayer3-arm/include/container.h create mode 100644 libeplayer3-arm/include/debug.h create mode 100644 libeplayer3-arm/include/ffmpeg_metadata.h create mode 100644 libeplayer3-arm/include/manager.h create mode 100644 libeplayer3-arm/include/misc.h create mode 100644 libeplayer3-arm/include/output.h create mode 100644 libeplayer3-arm/include/pcm.h create mode 100644 libeplayer3-arm/include/pes.h create mode 100644 libeplayer3-arm/include/playback.h create mode 100644 libeplayer3-arm/include/stm_ioctls.h create mode 100644 libeplayer3-arm/include/writer.h create mode 100644 libeplayer3-arm/main/exteplayer.c create mode 100644 libeplayer3-arm/manager/audio.c create mode 100644 libeplayer3-arm/manager/manager.c create mode 100644 libeplayer3-arm/manager/subtitle.c create mode 100644 libeplayer3-arm/manager/video.c create mode 100644 libeplayer3-arm/output/linuxdvb_mipsel.c create mode 100644 libeplayer3-arm/output/linuxdvb_sh4.c create mode 100644 libeplayer3-arm/output/output.c create mode 100644 libeplayer3-arm/output/output_subtitle.c create mode 100644 libeplayer3-arm/output/writer/common/misc.c create mode 100644 libeplayer3-arm/output/writer/common/pes.c create mode 100644 libeplayer3-arm/output/writer/mipsel/aac.c create mode 100644 libeplayer3-arm/output/writer/mipsel/ac3.c create mode 100644 libeplayer3-arm/output/writer/mipsel/amr.c create mode 100644 libeplayer3-arm/output/writer/mipsel/divx3.c create mode 100644 libeplayer3-arm/output/writer/mipsel/dts.c create mode 100644 libeplayer3-arm/output/writer/mipsel/h263.c create mode 100644 libeplayer3-arm/output/writer/mipsel/h264.c create mode 100644 libeplayer3-arm/output/writer/mipsel/h265.c create mode 100644 libeplayer3-arm/output/writer/mipsel/lpcm.c create mode 100644 libeplayer3-arm/output/writer/mipsel/mp3.c create mode 100644 libeplayer3-arm/output/writer/mipsel/mpeg2.c create mode 100644 libeplayer3-arm/output/writer/mipsel/mpeg4.c create mode 100644 libeplayer3-arm/output/writer/mipsel/pcm.c create mode 100644 libeplayer3-arm/output/writer/mipsel/vc1.c create mode 100644 libeplayer3-arm/output/writer/mipsel/vp.c create mode 100644 libeplayer3-arm/output/writer/mipsel/wma.c create mode 100644 libeplayer3-arm/output/writer/mipsel/wmv.c create mode 100644 libeplayer3-arm/output/writer/mipsel/writer.c create mode 100644 libeplayer3-arm/output/writer/sh4/aac.c create mode 100644 libeplayer3-arm/output/writer/sh4/ac3.c create mode 100644 libeplayer3-arm/output/writer/sh4/divx.c create mode 100644 libeplayer3-arm/output/writer/sh4/divx2.c create mode 100644 libeplayer3-arm/output/writer/sh4/dts.c create mode 100644 libeplayer3-arm/output/writer/sh4/h263.c create mode 100644 libeplayer3-arm/output/writer/sh4/h264.c create mode 100644 libeplayer3-arm/output/writer/sh4/mp3.c create mode 100644 libeplayer3-arm/output/writer/sh4/mpeg2.c create mode 100644 libeplayer3-arm/output/writer/sh4/pcm.c create mode 100644 libeplayer3-arm/output/writer/sh4/pes.c create mode 100644 libeplayer3-arm/output/writer/sh4/vc1.c create mode 100644 libeplayer3-arm/output/writer/sh4/vorbis.c create mode 100644 libeplayer3-arm/output/writer/sh4/wma.c create mode 100644 libeplayer3-arm/output/writer/sh4/wmv.c create mode 100644 libeplayer3-arm/output/writer/sh4/writer.c create mode 100644 libeplayer3-arm/playback/playback.c diff --git a/Makefile.am b/Makefile.am index a7fb1ad..8d112c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,4 +58,12 @@ SUBDIRS += libarmbox libdvbci libstb_hal_la_LIBADD += \ libarmbox/libarmbox.la \ libdvbci/libdvbci.la + +if !ENABLE_GSTREAMER_10 +SUBDIRS += libeplayer3-arm + +libstb_hal_la_LIBADD += \ + libeplayer3-arm/libeplayer3_arm.la +endif + endif diff --git a/configure.ac b/configure.ac index 9bdb071..492de39 100644 --- a/configure.ac +++ b/configure.ac @@ -25,32 +25,32 @@ if test x"$BOXTYPE" = x"tripledragon"; then fi AC_ARG_ENABLE(gstreamer_01, - AS_HELP_STRING(--enable-gstreamer_01,use gstreamer 0.10 playback), - ,[enable_gstreamer_01=no]) + AS_HELP_STRING(--enable-gstreamer_01, use gstreamer 0.10 playback), + ,[enable_gstreamer_01=no]) AM_CONDITIONAL(ENABLE_GSTREAMER_01,test "$enable_gstreamer_01" = "yes") if test "$enable_gstreamer_01" = "yes"; then - AC_DEFINE(ENABLE_GSTREAMER_01,1,[use gstreamer 0.10 playback]) - PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10]) - PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10]) + AC_DEFINE(ENABLE_GSTREAMER_01, 1, [use gstreamer 0.10 playback]) + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10]) + PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10]) fi AC_ARG_ENABLE(gstreamer_10, - AS_HELP_STRING(--enable-gstreamer_10,use gstreamer 1.0 playback), - ,[enable_gstreamer_10=no]) + AS_HELP_STRING(--enable-gstreamer_10, use gstreamer 1.0 playback), + ,[enable_gstreamer_10=no]) -AM_CONDITIONAL(ENABLE_GSTREAMER_10,test "$enable_gstreamer_10" = "yes") +AM_CONDITIONAL(ENABLE_GSTREAMER_10, test "$enable_gstreamer_10" = "yes") if test "$enable_gstreamer_10" = "yes"; then - AC_DEFINE(ENABLE_GSTREAMER_10,1,[use gstreamer 1.0 playback]) - PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) - PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) - PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) + AC_DEFINE(ENABLE_GSTREAMER_10, 1, [use gstreamer 1.0 playback]) + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) + PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) + PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) fi -if test x$BOXTYPE = xarmbox ; then - PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) - PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) - PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) +if test x$BOXTYPE = xarmbox && "$enable_gstreamer_10" = "yes"; then + PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0]) + PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0]) + PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0]) fi if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then @@ -66,6 +66,7 @@ AC_OUTPUT([ Makefile common/Makefile libeplayer3/Makefile +libeplayer3-arm/Makefile libthread/Makefile azbox/Makefile generic-pc/Makefile diff --git a/include/playback_hal.h b/include/playback_hal.h index 982a856..5891fd2 100644 --- a/include/playback_hal.h +++ b/include/playback_hal.h @@ -6,7 +6,11 @@ #elif HAVE_SPARK_HARDWARE #include "../libspark/playback_libeplayer3.h" #elif HAVE_ARM_HARDWARE +#if ENABLE_GSTREAMER_10 #include "../libarmbox/playback_gst.h" +#else +#include "../libarmbox/playback_libeplayer3.h" +#endif #elif HAVE_AZBOX_HARDWARE #include "../azbox/playback.h" #elif HAVE_GENERIC_HARDWARE diff --git a/libarmbox/Makefile.am b/libarmbox/Makefile.am index 065cd26..a9b63b3 100644 --- a/libarmbox/Makefile.am +++ b/libarmbox/Makefile.am @@ -13,10 +13,7 @@ AM_LDFLAGS = \ @AVUTIL_LIBS@ \ @AVCODEC_LIBS@ \ @SWRESAMPLE_LIBS@ \ - -lpthread -lasound -lrt \ - -lgstreamer-1.0 \ - -lgsttag-1.0 \ - -lgstmpegts-1.0 + -lpthread -lasound -lrt libarmbox_la_SOURCES = \ hardware_caps.c \ @@ -24,6 +21,24 @@ libarmbox_la_SOURCES = \ video.cpp \ audio.cpp \ init.cpp \ - playback_gst.cpp \ pwrmngr.cpp \ record.cpp + +if ENABLE_GSTREAMER_10 +libarmbox_la_SOURCES += \ + playback_gst.cpp + +AM_LDFLAGS += \ + -lgstreamer-1.0 \ + -lgsttag-1.0 \ + -lgstmpegts-1.0 +else +libarmbox_la_SOURCES += \ + playback_libeplayer3.cpp + +AM_CPPFLAGS += \ + -I$(top_srcdir)/libeplayer3-arm/include + +AM_LDFLAGS += \ + -lass +endif diff --git a/libarmbox/playback_libeplayer3.cpp b/libarmbox/playback_libeplayer3.cpp new file mode 100644 index 0000000..4cacd4c --- /dev/null +++ b/libarmbox/playback_libeplayer3.cpp @@ -0,0 +1,703 @@ +#define __USE_FILE_OFFSET64 1 +#include +#include +#include +#include +#include + +#include +#include + +#include +extern OutputHandler_t OutputHandler; +extern PlaybackHandler_t PlaybackHandler; +extern ContainerHandler_t ContainerHandler; +extern ManagerHandler_t ManagerHandler; + +#include "playback_libeplayer3.h" +#include "lt_debug.h" + +#define lt_debug(args...) _lt_debug(HAL_DEBUG_PLAYBACK, this, args) +#define lt_info(args...) _lt_info(HAL_DEBUG_PLAYBACK, this, args) + +static Context_t *player = NULL; + +extern cAudio *audioDecoder; +extern cVideo *videoDecoder; + +//Used by Fileplay +bool cPlayback::Open(playmode_t PlayMode) +{ + if (PlayMode != PLAYMODE_TS) + { + audioDecoder->closeDevice(); + videoDecoder->closeDevice(); + decoders_closed = true; + } + pm = PlayMode; + fn_ts = ""; + fn_xml = ""; + last_size = 0; + nPlaybackSpeed = 0; + init_jump = -1; + if (player) + free(player); + player = NULL; + player = (Context_t *) malloc(sizeof(Context_t)); + if (player) + { + player->playback = &PlaybackHandler; + player->output = &OutputHandler; + player->container = &ContainerHandler; + player->manager = &ManagerHandler; + lt_info("%s - player output name: %s\n", __func__, player->output->Name); + } + //Registration of output devices + if (player && player->output) + { + player->output->Command(player, OUTPUT_ADD, (void *)"audio"); + player->output->Command(player, OUTPUT_ADD, (void *)"video"); + } + return 0; +} + +void cPlayback::Close(void) +{ + lt_info("%s\n", __func__); + //Dagobert: movieplayer does not call stop, it calls close ;) + Stop(); + if (decoders_closed) + { + audioDecoder->openDevice(); + videoDecoder->openDevice(); + decoders_closed = false; + } +} + +bool cPlayback::Start(std::string filename, std::string headers) +{ + return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers); +} + +bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers) +{ + bool ret = false; + bool isHTTP = false; + no_probe = false; + lt_info("%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d\n", __func__, filename, vpid, vtype, apid, ac3); + init_jump = -1; + //create playback path + mAudioStream = 0; + mSubtitleStream = -1; + mTeletextStream = -1; + unlink("/tmp/.id3coverart"); + std::string file; + if (*filename == '/') + file = "file://"; + file += filename; + if ((file.find(":31339/id=") != std::string::npos) || (file.find(":10000") != std::string::npos) || (file.find(":8001/") != std::string::npos)) // for LocalTV and Entertain-TV streaming + no_probe = true; + if (file.substr(0, 7) == "file://") + { + if (file.substr(file.length() - 3) == ".ts") + { + fn_ts = file.substr(7); + fn_xml = file.substr(7, file.length() - 9); + fn_xml += "xml"; + no_probe = true; + } + } + else + isHTTP = true; + PlayFiles_t playbackFiles = { (char *) file.c_str(), NULL}; + if (player->playback->Command(player, PLAYBACK_OPEN, &playbackFiles) == 0) + { + if (pm == PLAYMODE_TS) + { + struct stat64 s; + if (!stat64(file.c_str(), &s)) + last_size = s.st_size; + ret = true; + videoDecoder->Stop(false); + audioDecoder->Stop(); + } + else + { + /* + //AUDIO + if(player && player->manager && player->manager->audio) { + char ** TrackList = NULL; + player->manager->audio->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("AudioTrack List\n"); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + + //SUB + if(player && player->manager && player->manager->subtitle) { + char ** TrackList = NULL; + player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("SubtitleTrack List\n"); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + //Teletext + if(player && player->manager && player->manager->teletext) { + char ** TrackList = NULL; + player->manager->teletext->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("TeletextTrack List\n"); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + //Chapters + if(player && player->manager && player->manager->chapter) { + char ** TrackList = NULL; + player->manager->chapter->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("Chapter List\n"); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + */ + playing = true; + player->output->Command(player, OUTPUT_OPEN, NULL); + ret = (player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0); + if (ret && !isHTTP) + playing = ret = (player->playback->Command(player, PLAYBACK_PAUSE, NULL) == 0); + } + } + return ret; +} + +bool cPlayback::Stop(void) +{ + lt_info("%s playing %d\n", __func__, playing); + if (player && player->playback) + player->playback->Command(player, PLAYBACK_STOP, NULL); + if (player && player->output) + player->output->Command(player, OUTPUT_CLOSE, NULL); + if (player && player->output) + { + player->output->Command(player, OUTPUT_DEL, (void *)"audio"); + player->output->Command(player, OUTPUT_DEL, (void *)"video"); + } + if (player && player->playback) + player->playback->Command(player, PLAYBACK_CLOSE, NULL); + playing = false; + return true; +} + +bool cPlayback::SetAPid(int pid, bool /* ac3 */) +{ + lt_info("%s\n", __func__); + int i = pid; + if (pid != mAudioStream) + { + if (player && player->playback) + player->playback->Command(player, PLAYBACK_SWITCH_AUDIO, (void *)&i); + mAudioStream = pid; + } + return true; +} + +bool cPlayback::SetVPid(int pid) +{ + lt_info("%s\n", __func__); + return true; +} + +bool cPlayback::SetSubtitlePid(int pid) +{ + lt_info("%s\n", __func__); + int i = pid; + if (pid != mSubtitleStream) + { + if (player && player->playback) + player->playback->Command(player, PLAYBACK_SWITCH_SUBTITLE, (void *)&i); + mSubtitleStream = pid; + } + return true; +} + +bool cPlayback::SetTeletextPid(int pid) +{ + lt_info("%s\n", __func__); + int i = pid; + if (pid != mTeletextStream) + { + //if(player && player->playback) + //player->playback->Command(player, PLAYBACK_SWITCH_TELETEXT, (void*)&i); + mTeletextStream = pid; + } + return true; +} + +bool cPlayback::SetSpeed(int speed) +{ + lt_info("%s playing %d speed %d\n", __func__, playing, speed); + if (!decoders_closed) + { + audioDecoder->closeDevice(); + videoDecoder->closeDevice(); + decoders_closed = true; + usleep(500000); + if (player && player->output && player->playback) + { + player->output->Command(player, OUTPUT_OPEN, NULL); + if (player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0) + playing = true; + } + } + if (!playing) + return false; + if (player && player->playback) + { + int result = 0; + nPlaybackSpeed = speed; + if (speed > 1) + { + /* direction switch ? */ + if (player->playback->BackWard) + { + int r = 0; + result = player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&r); + printf("result = %d\n", result); + } + result = player->playback->Command(player, PLAYBACK_FASTFORWARD, (void *)&speed); + } + else if (speed < 0) + { + /* direction switch ? */ + if (player->playback->isForwarding) + { + result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL); + printf("result = %d\n", result); + } + result = player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&speed); + } + else if (speed == 0) + { + /* konfetti: hmmm accessing the member isn't very proper */ + if ((player->playback->isForwarding) || (!player->playback->BackWard)) + player->playback->Command(player, PLAYBACK_PAUSE, NULL); + else + { + int _speed = 0; /* means end of reverse playback */ + player->playback->Command(player, PLAYBACK_FASTBACKWARD, (void *)&_speed); + } + } + else + { + result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL); + } + if (init_jump > -1) + { + SetPosition(init_jump); + init_jump = -1; + } + if (result != 0) + { + printf("returning false\n"); + return false; + } + } + return true; +} + +bool cPlayback::GetSpeed(int &speed) const +{ + lt_debug("%s\n", __func__); + speed = nPlaybackSpeed; + return true; +} + +void cPlayback::GetPts(uint64_t &pts) +{ + if (player && player->playback) + player->playback->Command(player, PLAYBACK_PTS, (void *)&pts); +} + +// in milliseconds +bool cPlayback::GetPosition(int &position, int &duration) +{ + bool got_duration = false; + lt_debug("%s %d %d\n", __func__, position, duration); + /* hack: if the file is growing (timeshift), then determine its length + * by comparing the mtime with the mtime of the xml file */ + if (pm == PLAYMODE_TS) + { + struct stat64 s; + if (!stat64(fn_ts.c_str(), &s)) + { + if (!playing || last_size != s.st_size) + { + last_size = s.st_size; + time_t curr_time = s.st_mtime; + if (!stat64(fn_xml.c_str(), &s)) + { + duration = (curr_time - s.st_mtime) * 1000; + if (!playing) + return true; + got_duration = true; + } + } + } + } + if (!playing) + return false; + if (player && player->playback && !player->playback->isPlaying) + { + lt_info("%s !!!!EOF!!!! < -1\n", __func__); + position = duration + 1000; + return false; + } + int64_t vpts = 0; + if (player && player->playback) + player->playback->Command(player, PLAYBACK_PTS, &vpts); + if (vpts <= 0) + { + //printf("ERROR: vpts==0"); + } + else + { + /* len is in nanoseconds. we have 90 000 pts per second. */ + position = vpts / 90; + } + if (got_duration) + return true; + int64_t length = 0; + if (player && player->playback) + player->playback->Command(player, PLAYBACK_LENGTH, &length); + if (length <= 0) + duration = duration + 1000; + else + duration = length * 1000; + return true; +} + +bool cPlayback::SetPosition(int position, bool absolute) +{ + lt_info("%s %d\n", __func__, position); + if (!playing) + { + /* the calling sequence is: + * Start() - paused + * SetPosition() - which fails if not running + * SetSpeed() - to start playing + * so let's remember the initial jump position and later jump to it + */ + init_jump = position; + return false; + } + int64_t pos = (position / 1000.0); + if (player && player->playback) + player->playback->Command(player, absolute ? PLAYBACK_SEEK_ABS : PLAYBACK_SEEK, (void *)&pos); + return true; +} + +void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language) +{ + lt_info("%s\n", __func__); + int max_numpida = *numpida; + *numpida = 0; + /* + if(player && player->manager && player->manager->audio) { + char ** TrackList = NULL; + player->manager->audio->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("AudioTrack List\n"); + int i = 0,j=0; + for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + if (j < max_numpida) { + int _pid; + char _lang[strlen(TrackList[i])]; + if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) { + apids[j]=_pid; + // atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC + if( !strncmp("A_MPEG/L3", TrackList[i+1], 9)) + ac3flags[j] = 3; + if( !strncmp("A_MP3", TrackList[i+1], 5)) + ac3flags[j] = 4; + else if(!strncmp("A_AC3", TrackList[i+1], 5)) + ac3flags[j] = 1; + else if(!strncmp("A_EAC3", TrackList[i+1], 6)) + ac3flags[j] = 7; + else if(!strncmp("A_DTS", TrackList[i+1], 5)) + ac3flags[j] = 6; + else if(!strncmp("A_AAC", TrackList[i+1], 5)) + ac3flags[j] = 5; + else if(!strncmp("A_PCM", TrackList[i+1], 5)) + ac3flags[j] = 0; //todo + else if(!strncmp("A_VORBIS", TrackList[i+1], 8)) + ac3flags[j] = 0; //todo + else if(!strncmp("A_FLAC", TrackList[i+1], 6)) + ac3flags[j] = 0; //todo + else + ac3flags[j] = 0; //todo + language[j]=std::string(_lang); + } + } + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + *numpida=j; + } + }*/ +} + +void cPlayback::FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language) +{ + lt_info("%s\n", __func__); + int max_numpids = *numpids; + *numpids = 0; + if (player && player->manager && player->manager->subtitle) + { + char **TrackList = NULL; + player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) + { + printf("SubtitleTrack List\n"); + int i = 0, j = 0; + for (i = 0, j = 0; TrackList[i] != NULL; i += 2, j++) + { + printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]); + if (j < max_numpids) + { + int _pid; + char _lang[strlen(TrackList[i])]; + if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) + { + pids[j] = _pid; + language[j] = std::string(_lang); + } + } + free(TrackList[i]); + free(TrackList[i + 1]); + } + free(TrackList); + *numpids = j; + } + } +} + +void cPlayback::FindAllTeletextsubtitlePids(int *pids, unsigned int *numpids, std::string *language, int *mags, int *pages) +{ + lt_info("%s\n", __func__); + /* + int max_numpids = *numpids; + *numpids = 0; + if(player && player->manager && player->manager->teletext) { + char ** TrackList = NULL; + player->manager->teletext->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("Teletext List\n"); + int i = 0,j=0; + for (i = 0,j=0; TrackList[i] != NULL; i+=2) { + int type = 0; + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + if (j < max_numpids) { + int _pid; + if (2 != sscanf(TrackList[i], "%*d %d %*s %d %*d %*d", &_pid, &type)) + continue; + if (type != 2 && type != 5) // return subtitles only + continue; + pids[j]=_pid; + language[j]=std::string(TrackList[i]); + j++; + } + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + *numpids=j; + } + } + */ +} + +int cPlayback::GetTeletextPid(void) +{ + lt_info("%s\n", __func__); + int pid = -1; + /* + if(player && player->manager && player->manager->teletext) { + char ** TrackList = NULL; + player->manager->teletext->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("Teletext List\n"); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + int type = 0; + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + if (pid < 0) { + if (2 != sscanf(TrackList[i], "%*d %d %*s %d %*d %*d", &pid, &type)) + continue; + if (type != 1) + pid = -1; + } + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + */ + printf("teletext pid id %d (0x%x)\n", pid, pid); + return pid; +} + +#if 0 +/* dummy functions for subtitles */ +void cPlayback::FindAllSubs(uint16_t * /*pids*/, unsigned short * /*supp*/, uint16_t *num, std::string * /*lang*/) +{ + *num = 0; +} + +bool cPlayback::SelectSubtitles(int /*pid*/) +{ + return false; +} +#endif + +void cPlayback::GetChapters(std::vector &positions, std::vector &titles) +{ + positions.clear(); + titles.clear(); + /* + if(player && player->manager && player->manager->chapter) { + char ** TrackList = NULL; + player->manager->chapter->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("%s: Chapter List\n", __func__); + int i = 0; + for (i = 0; TrackList[i] != NULL; i+=2) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + int pos = atoi(TrackList[i]); + std::string title(TrackList[i + 1]); + positions.push_back(pos); + titles.push_back(title); + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + } + } + */ +} + +void cPlayback::GetMetadata(std::vector &keys, std::vector &values) +{ + keys.clear(); + values.clear(); + char **metadata = NULL; + if (player && player->playback) + { + //player->playback->Command(player, PLAYBACK_METADATA, &metadata); + if (metadata) + { + for (char **m = metadata; *m;) + { + keys.push_back(*m); + free(*m++); + values.push_back(*m); + free(*m++); + } + free(metadata); + } + } +} + +cPlayback::cPlayback(int num __attribute__((unused))) +{ + lt_info("%s\n", __func__); + playing = false; + decoders_closed = false; +} + +cPlayback::~cPlayback() +{ + lt_info("%s\n", __func__); + if (player) + free(player); + player = NULL; +} + +void cPlayback::RequestAbort() +{ + if (player && player->playback) + { + player->playback->abortRequested = 1; + while (player->playback->isPlaying) + usleep(100000); + } +} + +bool cPlayback::IsPlaying() +{ + if (player && player->playback) + return player->playback->isPlaying; + return false; +} + +uint64_t cPlayback::GetReadCount() +{ + //if (player && player->playback) { + //return player->playback->readCount; + //} + return 0; +} + +AVFormatContext *cPlayback::GetAVFormatContext() +{ + return NULL; +} + +void cPlayback::ReleaseAVFormatContext() +{ +} + +#if 0 +bool cPlayback::IsPlaying(void) const +{ + lt_info("%s\n", __func__); + /* konfetti: there is no event/callback mechanism in libeplayer2 + * so in case of ending playback we have no information on a + * terminated stream currently (or did I oversee it?). + * So let's ask the player the state. + */ + if (playing) + { + return player->playback->isPlaying; + } + return playing; +} +#endif diff --git a/libarmbox/playback_libeplayer3.h b/libarmbox/playback_libeplayer3.h new file mode 100644 index 0000000..49817b2 --- /dev/null +++ b/libarmbox/playback_libeplayer3.h @@ -0,0 +1,91 @@ +#ifndef __HAL_PLAYBACK_H +#define __HAL_PLAYBACK_H + +#include +#include + +typedef enum +{ + PLAYMODE_TS = 0, + PLAYMODE_FILE +} playmode_t; + +struct AVFormatContext; + +class cPlayback +{ + friend class CStreamInfo2; + + private: + bool enabled; + bool playing; + bool no_probe; + int nPlaybackSpeed; + int mAudioStream; + int mSubtitleStream; + int mTeletextStream; + bool Stop(void); + bool decoders_closed; + playmode_t pm; + std::string fn_ts; + std::string fn_xml; + off64_t last_size; + int init_jump; + public: + cPlayback(int num = 0); + ~cPlayback(); + + bool Open(playmode_t PlayMode); + void Close(void); + bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = ""); + bool Start(std::string filename, std::string headers = ""); + bool SetAPid(int pid, bool ac3 = false); + bool SetVPid(int pid); + bool SetSubtitlePid(int pid); + bool SetTeletextPid(int pid); + int GetAPid(void) + { + return mAudioStream; + }; + int GetVPid(void) + { + return 0; + }; + int GetSubtitlePid(void) + { + return mSubtitleStream; + }; + int GetTeletextPid(void); + bool SetSpeed(int speed); + bool GetSpeed(int &speed) const; + bool GetPosition(int &position, int &duration); + void GetPts(uint64_t &pts); + bool SetPosition(int position, bool absolute = false); + void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language); + void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language); + void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages); + void RequestAbort(void); + bool IsPlaying(void); + uint64_t GetReadCount(void); + + void GetChapters(std::vector &positions, std::vector &titles); + void GetMetadata(std::vector &keys, std::vector &values); + + AVFormatContext *GetAVFormatContext(); + void ReleaseAVFormatContext(); +#if 0 + void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); + bool SelectSubtitles(int pid); + + // Functions that are not used by movieplayer.cpp: + bool GetOffset(off64_t &offset); + bool IsPlaying(void) const; + bool IsEnabled(void) const; + void *GetHandle(void); + void *GetDmHandle(void); + int GetCurrPlaybackSpeed(void) const; + void PlaybackNotify(int Event, void *pData, void *pTag); + void DMNotify(int Event, void *pTsBuf, void *Tag); +#endif +}; +#endif diff --git a/libeplayer3-arm/Makefile.am b/libeplayer3-arm/Makefile.am new file mode 100644 index 0000000..ceeea65 --- /dev/null +++ b/libeplayer3-arm/Makefile.am @@ -0,0 +1,49 @@ +AUTOMAKE_OPTIONS = subdir-objects + +noinst_LTLIBRARIES = libeplayer3_arm.la + +AM_CPPFLAGS = -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS +AM_CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE +AM_CPPFLAGS += -I$(srcdir)/include -I$(top_srcdir)/include +AM_CPPFLAGS += -I$(srcdir)/external +AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing + +libeplayer3_arm_la_SOURCES = \ + container/container.c \ + container/container_ffmpeg.c \ + manager/manager.c \ + manager/audio.c \ + manager/video.c \ + manager/subtitle.c \ + output/linuxdvb_mipsel.c \ + output/output_subtitle.c \ + output/output.c \ + output/writer/common/pes.c \ + output/writer/common/misc.c \ + output/writer/mipsel/writer.c \ + output/writer/mipsel/aac.c \ + output/writer/mipsel/ac3.c \ + output/writer/mipsel/mp3.c \ + output/writer/mipsel/pcm.c \ + output/writer/mipsel/lpcm.c \ + output/writer/mipsel/dts.c \ + output/writer/mipsel/amr.c \ + output/writer/mipsel/wma.c \ + output/writer/mipsel/h265.c \ + output/writer/mipsel/h264.c \ + output/writer/mipsel/h263.c \ + output/writer/mipsel/mpeg2.c \ + output/writer/mipsel/mpeg4.c \ + output/writer/mipsel/divx3.c \ + output/writer/mipsel/vp.c \ + output/writer/mipsel/wmv.c \ + output/writer/mipsel/vc1.c \ + playback/playback.c \ + external/ffmpeg/src/bitstream.c \ + external/ffmpeg/src/latmenc.c \ + external/ffmpeg/src/mpeg4audio.c + + +LIBEPLAYER3_LIBS = libeplayer3_arm.la +# -lpthread -lavformat -lavcodec -lavutil -lswresample -lm + diff --git a/libeplayer3-arm/README.md b/libeplayer3-arm/README.md new file mode 100644 index 0000000..a8fd777 --- /dev/null +++ b/libeplayer3-arm/README.md @@ -0,0 +1,2 @@ +# exteplayer3 +Core of movie player for E2 based on the libeplayer using the ffmpeg solution diff --git a/libeplayer3-arm/container/buff_ffmpeg.c b/libeplayer3-arm/container/buff_ffmpeg.c new file mode 100644 index 0000000..1f394dd --- /dev/null +++ b/libeplayer3-arm/container/buff_ffmpeg.c @@ -0,0 +1,601 @@ +/* + * Container handling for all stream's handled by ffmpeg + * konfetti 2010; based on code from crow + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define FILLBUFSIZE 0 +#define FILLBUFDIFF 1048576 +#define FILLBUFPAKET 5120 +#define FILLBUFSEEKTIME 3 //sec +#define TIMEOUT_MAX_ITERS 10 + +static int ffmpeg_buf_size = FILLBUFSIZE + FILLBUFDIFF; +static int ffmpeg_buf_seek_time = FILLBUFSEEKTIME; +static int(*ffmpeg_read_org)(void *opaque, uint8_t *buf, int buf_size) = NULL; +static int(*ffmpeg_real_read_org)(void *opaque, uint8_t *buf, int buf_size) = NULL; + +static int64_t(*ffmpeg_seek_org)(void *opaque, int64_t offset, int whence) = NULL; +static unsigned char *ffmpeg_buf_read = NULL; +static unsigned char *ffmpeg_buf_write = NULL; +static unsigned char *ffmpeg_buf = NULL; +static pthread_t fillerThread; +static int hasfillerThreadStarted[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +int hasfillerThreadStartedID = 0; +static pthread_mutex_t fillermutex; +static int ffmpeg_buf_valid_size = 0; +static int ffmpeg_do_seek_ret = 0; +static int ffmpeg_do_seek = 0; +static int ffmpeg_buf_stop = 0; + +static Context_t *g_context = 0; +static int64_t playPts = -1; +static int32_t finishTimeout = 0; +static int8_t pauseTimeout = 0; +static int64_t maxInjectedPTS = INVALID_PTS_VALUE; + +static int64_t update_max_injected_pts(int64_t pts) +{ + if (pts > 0 && pts != INVALID_PTS_VALUE) + { + if (maxInjectedPTS == INVALID_PTS_VALUE || pts > maxInjectedPTS) + { + maxInjectedPTS = pts; + } + } + return maxInjectedPTS; +} + +int64_t get_play_pts() +{ + return playPts; +} + +void reset_finish_timeout() +{ + playPts = -1; + finishTimeout = 0; +} + +void set_pause_timeout(uint8_t pause) +{ + reset_finish_timeout(); + pauseTimeout = pause; +} + +static int8_t is_finish_timeout() +{ + if (finishTimeout > TIMEOUT_MAX_ITERS) + { + return 1; + } + return 0; +} + +static void update_finish_timeout() +{ + if (0 == pauseTimeout) + { + int64_t maxInjectedPts = update_max_injected_pts(-1); + int64_t currPts = -1; + int32_t ret = g_context->playback->Command(g_context, PLAYBACK_PTS, &currPts); + finishTimeout += 1; + if (maxInjectedPts < 0 || maxInjectedPts == INVALID_PTS_VALUE) + { + maxInjectedPts = 0; + } + //printf("ret[%d] playPts[%lld] currPts[%lld] maxInjectedPts[%lld]\n", ret, playPts, currPts, maxInjectedPts); + /* On some STBs PTS readed from decoder is invalid after seek or at start + * this is the reason for additional validation when we what to close immediately + */ + if (!progressive_playback && 0 == ret && currPts >= maxInjectedPts && + ((currPts - maxInjectedPts) / 90000) < 2) + { + /* close immediately + */ + finishTimeout = TIMEOUT_MAX_ITERS + 1; + } + else if (0 == ret && (playPts != currPts && maxInjectedPts > currPts)) + { + playPts = currPts; + finishTimeout = 0; + } + } +} + +static int32_t ffmpeg_read_wrapper_base(void *opaque, uint8_t *buf, int32_t buf_size, uint8_t type) +{ + int32_t len = 0; + if (0 == PlaybackDieNow(0)) + { + len = ffmpeg_real_read_org(opaque, buf, buf_size); + while (len < buf_size && g_context && 0 == PlaybackDieNow(0)) + { + if (type && len > 0) + { + break; + } + int32_t partLen = ffmpeg_real_read_org(opaque, buf + len, buf_size - len); + if (partLen > 0) + { + len += partLen; + finishTimeout = 0; + continue; + } + else if (is_finish_timeout()) + { + len = 0; + break; + } + update_finish_timeout(); + usleep(100000); + continue; + } + } + //printf("len [%d] finishTimeout[%d]\n", len, finishTimeout); + return len; +} + +static int32_t ffmpeg_read_wrapper(void *opaque, uint8_t *buf, int32_t buf_size) +{ + if (progressive_playback) + { + return ffmpeg_read_wrapper_base(opaque, buf, buf_size, 0); + } + else + { + /* at start it was progressive playback, but dwonload, finished + */ + return ffmpeg_real_read_org(opaque, buf, buf_size); + } +} + +static int32_t ffmpeg_read_wrapper2(void *opaque, uint8_t *buf, int32_t buf_size) +{ + return ffmpeg_read_wrapper_base(opaque, buf, buf_size, 1); +} + +//for buffered io +void getfillerMutex(const char *filename, const char *function, int line) +{ + ffmpeg_printf(100, "::%d requesting mutex\n", line); + pthread_mutex_lock(&fillermutex); + ffmpeg_printf(100, "::%d received mutex\n", line); +} + +void releasefillerMutex(const char *filename, const const char *function, int line) +{ + pthread_mutex_unlock(&fillermutex); + ffmpeg_printf(100, "::%d released mutex\n", line); +} +//for buffered io (end)encoding + +static int32_t container_set_ffmpeg_buf_seek_time(int32_t *time) +{ + ffmpeg_buf_seek_time = (*time); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_set_ffmpeg_buf_size(int32_t *size) +{ + if (ffmpeg_buf == NULL) + { + if (*size == 0) + { + ffmpeg_buf_size = 0; + } + else + { + ffmpeg_buf_size = (*size) + FILLBUFDIFF; + } + } + ffmpeg_printf(10, "size=%d, buffer size=%d\n", (*size), ffmpeg_buf_size); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_get_ffmpeg_buf_size(int32_t *size) +{ + *size = ffmpeg_buf_size - FILLBUFDIFF; + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_get_fillbufstatus(int32_t *size) +{ + int32_t rwdiff = 0; + if (ffmpeg_buf != NULL && ffmpeg_buf_read != NULL && ffmpeg_buf_write != NULL) + { + if (ffmpeg_buf_read < ffmpeg_buf_write) + rwdiff = ffmpeg_buf_write - ffmpeg_buf_read; + if (ffmpeg_buf_read > ffmpeg_buf_write) + { + rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; + rwdiff += ffmpeg_buf_write - ffmpeg_buf; + } + *size = rwdiff; + } + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_stop_buffer() +{ + ffmpeg_buf_stop = 1; + return 0; +} + +//flag 0: start direct +//flag 1: from thread +static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int32_t flag) +{ + int32_t len = 0; + int32_t rwdiff = ffmpeg_buf_size; + uint8_t buf[FILLBUFPAKET]; + if (ffmpeg_read_org == NULL || ffmpeg_seek_org == NULL) + { + ffmpeg_err("ffmpeg_read_org or ffmpeg_seek_org is NULL\n"); + return; + } + while ((flag == 0 && avContextTab[0] != NULL && avContextTab[0]->pb != NULL && rwdiff > FILLBUFDIFF) || + (flag == 1 && hasfillerThreadStarted[id] == 1 && avContextTab[0] != NULL && avContextTab[0]->pb != NULL && rwdiff > FILLBUFDIFF)) + { + if (0 == PlaybackDieNow(0)) + { + break; + } + if (flag == 0 && ffmpeg_buf_stop == 1) + { + ffmpeg_buf_stop = 0; + break; + } + getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + //do a seek + if (ffmpeg_do_seek != 0) + { + ffmpeg_do_seek_ret = ffmpeg_seek_org(avContextTab[0]->pb->opaque, avContextTab[0]->pb->pos + ffmpeg_do_seek, SEEK_SET); + if (ffmpeg_do_seek_ret >= 0) + { + ffmpeg_buf_write = ffmpeg_buf; + ffmpeg_buf_read = ffmpeg_buf; + } + ffmpeg_do_seek = 0; + } + if (ffmpeg_buf_read == ffmpeg_buf_write) + { + ffmpeg_buf_valid_size = 0; + rwdiff = ffmpeg_buf_size; + } + if (ffmpeg_buf_read < ffmpeg_buf_write) + { + rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_write; + rwdiff += ffmpeg_buf_read - ffmpeg_buf; + } + if (ffmpeg_buf_read > ffmpeg_buf_write) + { + rwdiff = ffmpeg_buf_read - ffmpeg_buf_write; + } + int32_t size = FILLBUFPAKET; + if (rwdiff - FILLBUFDIFF < size) + { + size = (rwdiff - FILLBUFDIFF); + } + if (ffmpeg_buf_write + size > ffmpeg_buf + ffmpeg_buf_size) + { + size = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_write; + } + if (ffmpeg_buf_write == ffmpeg_buf + ffmpeg_buf_size) + { + ffmpeg_buf_write = ffmpeg_buf; + } + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (size > 0) + { + if (flag == 1 && hasfillerThreadStarted[id] == 2) break; + len = ffmpeg_read_org(avContextTab[0]->pb->opaque, buf, size); + if (flag == 1 && hasfillerThreadStarted[id] == 2) break; + ffmpeg_printf(20, "buffer-status (free buffer=%d)\n", rwdiff - FILLBUFDIFF - len); + getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (len > 0) + { + memcpy(ffmpeg_buf_write, buf, len); + ffmpeg_buf_write += len; + } + else + { + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + ffmpeg_err("read not ok ret=%d\n", len); + break; + } + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + } + else + { + //on long pause the server close the connection, so we use seek to reconnect + if (context != NULL && context->playback != NULL && inpause != NULL) + { + if ((*inpause) == 0 && context->playback->isPaused) + { + (*inpause) = 1; + } + else if ((*inpause) == 1 && !context->playback->isPaused) + { + int32_t buflen = 0; + (*inpause) = 0; + getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (ffmpeg_buf_read < ffmpeg_buf_write) + { + buflen = ffmpeg_buf_write - ffmpeg_buf_read; + } + if (ffmpeg_buf_read > ffmpeg_buf_write) + { + buflen = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; + buflen += ffmpeg_buf_write - ffmpeg_buf; + } + ffmpeg_seek_org(avContextTab[0]->pb->opaque, avContextTab[0]->pb->pos + buflen, SEEK_SET); + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + } + } + } + } +} + +static void ffmpeg_fillerTHREAD(Context_t *context) +{ + int32_t inpause = 0; + int32_t id = hasfillerThreadStartedID; + ffmpeg_printf(10, "Running ID=%d!\n", id); + while (hasfillerThreadStarted[id] == 1) + { + ffmpeg_filler(context, id, &inpause, 1); + usleep(10000); + } + hasfillerThreadStarted[id] = 0; + ffmpeg_printf(10, "terminating ID=%d\n", id); +} + +static int32_t ffmpeg_start_fillerTHREAD(Context_t *context) +{ + int32_t error; + int32_t ret = 0, i = 0; + pthread_attr_t attr; + ffmpeg_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) + { + ffmpeg_printf(10, "is Playing\n"); + } + else + { + ffmpeg_printf(10, "is NOT Playing\n"); + } + //get filler thread ID + //if the thread hangs for long time, we use a new id + for (i = 0; i < 10; i++) + { + if (hasfillerThreadStarted[i] == 0) + { + hasfillerThreadStartedID = i; + break; + } + } + if (hasfillerThreadStarted[hasfillerThreadStartedID] == 0) + { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + hasfillerThreadStarted[hasfillerThreadStartedID] = 1; + if ((error = pthread_create(&fillerThread, &attr, (void *)&ffmpeg_fillerTHREAD, context)) != 0) + { + hasfillerThreadStarted[hasfillerThreadStartedID] = 0; + ffmpeg_printf(10, "Error creating filler thread, error:%d:%s\n", error, strerror(error)); + ret = cERR_CONTAINER_FFMPEG_ERR; + } + else + { + ffmpeg_printf(10, "Created filler thread\n"); + } + } + else + { + ffmpeg_printf(10, "All filler thread ID's in use!\n"); + ret = cERR_CONTAINER_FFMPEG_ERR; + } + ffmpeg_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t ffmpeg_read_real(void *opaque, uint8_t *buf, int32_t buf_size) +{ + int32_t len = buf_size; + int32_t rwdiff = 0; + if (buf_size > 0) + { + getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (ffmpeg_buf_read < ffmpeg_buf_write) + rwdiff = ffmpeg_buf_write - ffmpeg_buf_read; + if (ffmpeg_buf_read > ffmpeg_buf_write) + { + rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; + rwdiff += ffmpeg_buf_write - ffmpeg_buf; + } + rwdiff--; + if (len > rwdiff) + { + len = rwdiff; + } + if (ffmpeg_buf_read + len > ffmpeg_buf + ffmpeg_buf_size) + { + len = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; + } + if (len > 0) + { + memcpy(buf, ffmpeg_buf_read, len); + ffmpeg_buf_read += len; + if (ffmpeg_buf_valid_size < FILLBUFDIFF) + { + if (ffmpeg_buf_valid_size + len > FILLBUFDIFF) + { + ffmpeg_buf_valid_size = FILLBUFDIFF; + } + else + { + ffmpeg_buf_valid_size += len; + } + } + if (ffmpeg_buf_read == ffmpeg_buf + ffmpeg_buf_size) + { + ffmpeg_buf_read = ffmpeg_buf; + } + } + else + { + len = 0; + } + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + } + return len; +} + +static int32_t ffmpeg_read(void *opaque, uint8_t *buf, int32_t buf_size) +{ + int32_t sumlen = 0; + int32_t len = 0; + int32_t count = 2000; + while (sumlen < buf_size && (--count) > 0 && 0 == PlaybackDieNow(0)) + { + len = ffmpeg_read_real(opaque, buf, buf_size - sumlen); + sumlen += len; + buf += len; + if (len == 0) + { + usleep(10000); + } + } + if (count == 0) + { + if (sumlen == 0) + { + ffmpeg_err("Timeout waiting for buffered data (buf_size=%d sumlen=%d)!\n", buf_size, sumlen); + } + else + { + ffmpeg_err("Timeout, not all buffered data availabel (buf_size=%d sumlen=%d)!\n", buf_size, sumlen); + } + } + return sumlen; +} + +static int64_t ffmpeg_seek(void *opaque, int64_t offset, int32_t whence) +{ + int64_t diff; + int32_t rwdiff = 0; + whence &= ~AVSEEK_FORCE; + if (whence != SEEK_CUR && whence != SEEK_SET) + { + return AVERROR(EINVAL); + } + if (whence == SEEK_CUR) + { + diff = offset; + } + else + { + diff = offset - avContextTab[0]->pb->pos; + } + if (diff == 0) + { + return avContextTab[0]->pb->pos; + } + getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (ffmpeg_buf_read < ffmpeg_buf_write) + { + rwdiff = ffmpeg_buf_write - ffmpeg_buf_read; + } + if (ffmpeg_buf_read > ffmpeg_buf_write) + { + rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; + rwdiff += ffmpeg_buf_write - ffmpeg_buf; + } + if (diff > 0 && diff < rwdiff) + { + /* can do the seek inside the buffer */ + ffmpeg_printf(20, "buffer-seek diff=%lld\n", diff); + if (diff > (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read) + { + ffmpeg_buf_read = ffmpeg_buf + (diff - ((ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read)); + } + else + { + ffmpeg_buf_read = ffmpeg_buf_read + diff; + } + } + else if (diff < 0 && diff * -1 < ffmpeg_buf_valid_size) + { + /* can do the seek inside the buffer */ + ffmpeg_printf(20, "buffer-seek diff=%lld\n", diff); + int32_t tmpdiff = diff * -1; + if (tmpdiff > ffmpeg_buf_read - ffmpeg_buf) + { + ffmpeg_buf_read = (ffmpeg_buf + ffmpeg_buf_size) - (tmpdiff - (ffmpeg_buf_read - ffmpeg_buf)); + } + else + { + ffmpeg_buf_read = ffmpeg_buf_read - tmpdiff; + } + } + else + { + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + ffmpeg_printf(20, "real-seek diff=%lld\n", diff); + ffmpeg_do_seek_ret = 0; + ffmpeg_do_seek = diff; + while (ffmpeg_do_seek != 0) + { + usleep(100000); + } + ffmpeg_do_seek = 0; + if (ffmpeg_do_seek_ret < 0) + { + ffmpeg_err("seek not ok ret=%d\n", ffmpeg_do_seek_ret); + return ffmpeg_do_seek_ret; + } + //fill buffer + int32_t count = ffmpeg_buf_seek_time * 10; + int32_t size = 0; + container_get_fillbufstatus(&size); + while (size < ffmpeg_buf_size - FILLBUFDIFF && (--count) > 0) + { + usleep(100000); + container_get_fillbufstatus(&size); + } + return avContextTab[0]->pb->pos + diff; + } + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); + return avContextTab[0]->pb->pos + diff; +} + +static void ffmpeg_buf_free() +{ + ffmpeg_read_org = NULL; + ffmpeg_seek_org = NULL; + ffmpeg_buf_read = NULL; + ffmpeg_buf_write = NULL; + free(ffmpeg_buf); + ffmpeg_buf = NULL; + ffmpeg_buf_valid_size = 0; + ffmpeg_do_seek_ret = 0; + ffmpeg_do_seek = 0; + ffmpeg_buf_stop = 0; + hasfillerThreadStartedID = 0; +} diff --git a/libeplayer3-arm/container/container.c b/libeplayer3-arm/container/container.c new file mode 100644 index 0000000..384a46e --- /dev/null +++ b/libeplayer3-arm/container/container.c @@ -0,0 +1,137 @@ +/* + * Main Container Handling. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include "common.h" + +#ifdef SAM_WITH_DEBUG +#define CONTAINER_DEBUG +#else +#define CONTAINER_SILENT +#endif + +#ifdef CONTAINER_DEBUG + +static short debug_level = 0; + +#define container_printf(level, x...) do { \ + if (debug_level >= level) printf(x); } while (0) +#else +#define container_printf(level, x...) +#endif + +#ifndef CONTAINER_SILENT +#define container_err(x...) do { printf(x); } while (0) +#else +#define container_err(x...) +#endif + +static Container_t *AvailableContainer[] = +{ + &FFMPEGContainer, + NULL +}; + +static void printContainerCapabilities() +{ + int32_t i = 0; + int32_t j = 0; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + container_printf(10, "Capabilities: "); + for (i = 0; AvailableContainer[i] != NULL; i++) + { + for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++) + { + container_printf(10, "%s ", AvailableContainer[i]->Capabilities[j]); + } + } + container_printf(10, "\n"); +} + +static int32_t selectContainer(Context_t *context, char *extension) +{ + int32_t i = 0; + int32_t j = 0; + int32_t ret = -1; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + for (i = 0; AvailableContainer[i] != NULL; i++) + { + for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++) + { + if (!strcasecmp(AvailableContainer[i]->Capabilities[j], extension)) + { + context->container->selectedContainer = AvailableContainer[i]; + container_printf(10, "Selected Container: %s\n", context->container->selectedContainer->Name); + ret = 0; + break; + } + } + if (ret == 0) + { + break; + } + } + if (ret != 0) + { + container_err("No Container found :-(\n"); + } + return ret; +} + + +static int Command(void *_context, ContainerCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = 0; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + switch (command) + { + case CONTAINER_ADD: + { + ret = selectContainer(context, (char *) argument); + break; + } + case CONTAINER_CAPABILITIES: + { + printContainerCapabilities(); + break; + } + case CONTAINER_DEL: + { + context->container->selectedContainer = NULL; + break; + } + default: + container_err("%s::%s ContainerCmd %d not supported!\n", __FILE__, __FUNCTION__, command); + break; + } + return ret; +} + + +ContainerHandler_t ContainerHandler = +{ + "Output", + NULL, + Command +}; diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c new file mode 100644 index 0000000..9a51039 --- /dev/null +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -0,0 +1,2684 @@ +/* + * Container handling for all stream's handled by ffmpeg + * konfetti 2010; based on code from crow + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* Support Large File */ +#define _FILE_OFFSET_BITS 64 + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "misc.h" +#include "debug.h" +#include "aac.h" +#include "pcm.h" +#include "ffmpeg_metadata.h" +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#if (LIBAVFORMAT_VERSION_MAJOR > 57) +#define TS_BYTES_SEEKING 0 +#else +#define TS_BYTES_SEEKING 1 +#endif + +/* Some STB with old kernels have problem with default + * read/write functions in ffmpeg which use open/read + * due to this we set own which use fopen/fread from + * std library. + */ +#define SAM_CUSTOM_IO + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define FFMPEG_DEBUG +#else +#define FFMPEG_SILENT +#endif + +#ifdef FFMPEG_DEBUG + +static short debug_level = 1; + +#define ffmpeg_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ffmpeg_printf(level, fmt, x...) +#endif + +#ifndef FFMPEG_SILENT +#define ffmpeg_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ffmpeg_err(fmt, x...) +#endif + +/* Error Constants */ +#define cERR_CONTAINER_FFMPEG_NO_ERROR 0 +#define cERR_CONTAINER_FFMPEG_INIT -1 +#define cERR_CONTAINER_FFMPEG_NOT_SUPPORTED -2 +#define cERR_CONTAINER_FFMPEG_INVALID_FILE -3 +#define cERR_CONTAINER_FFMPEG_RUNNING -4 +#define cERR_CONTAINER_FFMPEG_NOMEM -5 +#define cERR_CONTAINER_FFMPEG_OPEN -6 +#define cERR_CONTAINER_FFMPEG_STREAM -7 +#define cERR_CONTAINER_FFMPEG_NULL -8 +#define cERR_CONTAINER_FFMPEG_ERR -9 +#define cERR_CONTAINER_FFMPEG_END_OF_FILE -10 + +#define IPTV_AV_CONTEXT_MAX_NUM 2 +/* ***************************** */ +/* Types */ +/* ***************************** */ +typedef enum {RTMP_NATIVE, RTMP_LIBRTMP, RTMP_NONE} eRTMPProtoImplType; + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static pthread_mutex_t mutex; + +static pthread_t PlayThread; +static int32_t hasPlayThreadStarted = 0; + +static AVFormatContext *avContextTab[IPTV_AV_CONTEXT_MAX_NUM] = {NULL, NULL}; +static int32_t use_custom_io[IPTV_AV_CONTEXT_MAX_NUM] = {0, 0}; +static AVDictionary *avio_opts = NULL; + +static uint8_t isContainerRunning = 0; + +static int64_t latestPts = 0; + +static int32_t restart_audio_resampling = 0; + +static off_t seek_target_bytes = 0; +static int32_t do_seek_target_bytes = 0; + +static int64_t seek_target_seconds = 0; +static int8_t do_seek_target_seconds = 0; +static int64_t prev_seek_time_sec = -1; + +static int32_t seek_target_flag = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ +static int32_t container_ffmpeg_seek_bytes(off_t pos); +static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute); +static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec); +static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length); +static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts); + +/* Progressive playback means that we play local file + * but this local file can grows up, for example + * we start playback before download was finished + */ +static int32_t progressive_playback = 0; +void progressive_playback_set(int32_t val) +{ + progressive_playback = val; +} + +#include "buff_ffmpeg.c" +#include "wrapped_ffmpeg.c" +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) +#include "mpeg4p2_ffmpeg.c" +#endif + +#ifdef HAVE_FLV2MPEG4_CONVERTER +#include "flv2mpeg4_ffmpeg.c" +#endif + +/* This is also bad solution + * such configuration should passed maybe + * via struct + */ +static int32_t wma_software_decode = 0; +static int32_t aac_software_decode = 0; +#ifdef __sh__ +static int32_t aac_latm_software_decode = 1; +#else +static int32_t aac_latm_software_decode = 0; +#endif + +static int32_t ac3_software_decode = 0; +static int32_t eac3_software_decode = 0; +static int32_t dts_software_decode = 0; +static int32_t pcm_resampling = 1; +static int32_t stereo_software_decoder = 0; +static int32_t insert_pcm_as_lpcm = 0; +static int32_t mp3_software_decode = 0; +static int32_t rtmp_proto_impl = 0; // 0 - auto, 1 - native, 2 - librtmp + +static int32_t g_sel_program_id = -1; + +#ifdef HAVE_FLV2MPEG4_CONVERTER +static int32_t flv2mpeg4_converter = 1; +#else +static int32_t flv2mpeg4_converter = 0; +#endif + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static void ffmpeg_silen_callback(void *avcl, int level, const char *fmt, va_list vl) +{ + return; +} + +static int32_t mutexInitialized = 0; + +void sel_program_id_set(const int32_t val) +{ + g_sel_program_id = val; +} + +void wma_software_decoder_set(const int32_t val) +{ + wma_software_decode = val; +} + +void aac_software_decoder_set(const int32_t val) +{ + aac_software_decode = val; +} + +void aac_latm_software_decoder_set(const int32_t val) +{ + aac_latm_software_decode = val; +} + +void ac3_software_decoder_set(const int32_t val) +{ + ac3_software_decode = val; +} + +void eac3_software_decoder_set(const int32_t val) +{ + eac3_software_decode = val; +} + +void dts_software_decoder_set(const int32_t val) +{ + dts_software_decode = val; +} + +void stereo_software_decoder_set(const int32_t val) +{ + stereo_software_decoder = val; +} + +void insert_pcm_as_lpcm_set(const int32_t val) +{ + insert_pcm_as_lpcm = val; +} + +void pcm_resampling_set(const int32_t val) +{ + pcm_resampling = val; +} + +void mp3_software_decoder_set(const int32_t val) +{ + mp3_software_decode = val; +} + +void rtmp_proto_impl_set(const int32_t val) +{ + rtmp_proto_impl = val; +} + +void flv2mpeg4_converter_set(const int32_t val) +{ + flv2mpeg4_converter = val; +} + +int32_t ffmpeg_av_dict_set(const char *key, const char *value, int32_t flags) +{ + return av_dict_set(&avio_opts, key, value, flags); +} + +static void initMutex(void) +{ + pthread_mutex_init(&mutex, NULL); + mutexInitialized = 1; +} + +static void getMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int32_t line) +{ + ffmpeg_printf(100, "::%d requesting mutex\n", line); + if (!mutexInitialized) + { + initMutex(); + } + pthread_mutex_lock(&mutex); + ffmpeg_printf(100, "::%d received mutex\n", line); +} + +static void releaseMutex(const char *filename __attribute__((unused)), const const char *function __attribute__((unused)), int32_t line) +{ + pthread_mutex_unlock(&mutex); + ffmpeg_printf(100, "::%d released mutex\n", line); +} + +static char *Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extradata, int extradata_size, int profile, int32_t *version) +{ + ffmpeg_printf(10, "Codec ID: %d (%.8lx)\n", codec_id, codec_id); + switch (codec_id) + { + case AV_CODEC_ID_MPEG1VIDEO: + return "V_MPEG1"; + case AV_CODEC_ID_MPEG2VIDEO: + return "V_MPEG1"; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + case AV_CODEC_ID_H263I: + return "V_H263"; + case AV_CODEC_ID_FLV1: + return flv2mpeg4_converter ? "V_MPEG4" : "V_FLV"; + case AV_CODEC_ID_VP5: + case AV_CODEC_ID_VP6: + case AV_CODEC_ID_VP6F: + return "V_VP6"; + case AV_CODEC_ID_VP8: + return "V_VP8"; +#if LIBAVCODEC_VERSION_MAJOR > 54 + case AV_CODEC_ID_VP9: + return "V_VP9"; +#endif + case AV_CODEC_ID_RV10: + case AV_CODEC_ID_RV20: + return "V_RMV"; + case AV_CODEC_ID_MPEG4: + return "V_MPEG4"; +#if LIBAVCODEC_VERSION_MAJOR < 53 + case AV_CODEC_ID_XVID: +#endif + case AV_CODEC_ID_MSMPEG4V1: + case AV_CODEC_ID_MSMPEG4V2: + case AV_CODEC_ID_MSMPEG4V3: + return "V_DIVX3"; + case AV_CODEC_ID_WMV1: + *version = 1; + return "V_WMV"; + case AV_CODEC_ID_WMV2: + *version = 2; + return "V_WMV"; + case AV_CODEC_ID_WMV3: + *version = 3; + return "V_WMV"; + case AV_CODEC_ID_VC1: + return "V_VC1"; + case AV_CODEC_ID_H264: +#if LIBAVCODEC_VERSION_MAJOR < 54 + case AV_CODEC_ID_FFH264: +#endif + return "V_MPEG4/ISO/AVC"; +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(55, 92, 100) + case AV_CODEC_ID_HEVC: + // case AV_CODEC_ID_H265: + return "V_HEVC"; +#endif + case AV_CODEC_ID_AVS: + return "V_AVS"; + case AV_CODEC_ID_MP2: + return "A_MPEG/L3"; + case AV_CODEC_ID_MP3: + return (mp3_software_decode) ? "A_IPCM" : "A_MP3"; + case AV_CODEC_ID_AAC: + if (extradata_size >= 2) + { + MPEG4AudioConfig m4ac; + int off = avpriv_mpeg4audio_get_config(&m4ac, extradata, extradata_size * 8, 1); + ffmpeg_printf(1, "aac [%d] off[%d]\n", m4ac.object_type, off); + if (off < 0 || 2 != m4ac.object_type) + { + return "A_IPCM"; + } + } + return (aac_software_decode) ? "A_IPCM" : "A_AAC"; + case AV_CODEC_ID_AAC_LATM: + return (aac_latm_software_decode) ? "A_IPCM" : "A_AAC_LATM"; + case AV_CODEC_ID_AC3: + return (ac3_software_decode) ? "A_IPCM" : "A_AC3"; + case AV_CODEC_ID_EAC3: + return (eac3_software_decode) ? "A_IPCM" : "A_EAC3"; + case AV_CODEC_ID_DTS: + return (dts_software_decode) ? "A_IPCM" : "A_DTS"; + case AV_CODEC_ID_WMAV1: + case AV_CODEC_ID_WMAV2: + return (wma_software_decode) ? "A_IPCM" : "A_WMA"; + case 86056: + case AV_CODEC_ID_WMAPRO: + return (wma_software_decode) ? "A_IPCM" : "A_WMA/PRO"; + case AV_CODEC_ID_WMALOSSLESS: + return "A_IPCM"; + case AV_CODEC_ID_MLP: + return "A_IPCM"; + case AV_CODEC_ID_RA_144: + return "A_IPCM"; + case AV_CODEC_ID_RA_288: + return "A_IPCM"; + case AV_CODEC_ID_VORBIS: + return "A_IPCM"; + case AV_CODEC_ID_FLAC: + return "A_IPCM"; + case AV_CODEC_ID_PCM_S8: + case AV_CODEC_ID_PCM_U8: + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S16BE: + case AV_CODEC_ID_PCM_U16LE: + case AV_CODEC_ID_PCM_U16BE: + case AV_CODEC_ID_PCM_S24LE: + case AV_CODEC_ID_PCM_S24BE: + case AV_CODEC_ID_PCM_U24LE: + case AV_CODEC_ID_PCM_U24BE: + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_U32LE: + case AV_CODEC_ID_PCM_U32BE: + return pcm_resampling ? "A_IPCM" : "A_PCM"; + case AV_CODEC_ID_AMR_NB: + return "A_IPCM";//return "A_AMR"; + /* In exteplayer3 embedded text subtitle simple printed + * to output like other data. Maybe worth to consider is to use + * linux socket or pipe to put + */ + /* subtitle */ + case AV_CODEC_ID_SSA: +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100) + case AV_CODEC_ID_ASS: +#endif + return "S_TEXT/ASS"; /* Hellmaster1024: seems to be ASS instead of SSA */ + case AV_CODEC_ID_DVD_SUBTITLE: + case AV_CODEC_ID_DVB_SUBTITLE: + case AV_CODEC_ID_XSUB: + case AV_CODEC_ID_MOV_TEXT: + case AV_CODEC_ID_HDMV_PGS_SUBTITLE: + case AV_CODEC_ID_DVB_TELETEXT: +// case CODEC_ID_DVB_TELETEXT: +// return "S_TEXT/SRT"; /* fixme */ + case AV_CODEC_ID_TEXT: ///< raw UTF-8 text + return "S_TEXT/UTF-8"; + case AV_CODEC_ID_SRT: + return "S_TEXT/SRT"; + case AV_CODEC_ID_SUBRIP: + return "S_TEXT/SUBRIP"; + default: + ffmpeg_err("Codec ID %d (%.8lx) not found\n", codec_id, codec_id); + // Default to injected-pcm for unhandled audio types. + if (media_type == AVMEDIA_TYPE_AUDIO) + { + return "A_IPCM"; + } + ffmpeg_err("Codec ID %d (%.8lx) not found\n", codec_id, codec_id); + } + return NULL; +} + +static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts) +{ + if (!stream || pts == (int64_t)AV_NOPTS_VALUE) + { + ffmpeg_err("stream / packet null\n"); + return INVALID_PTS_VALUE; + } + else if (stream->time_base.den > 0) + { + pts = av_rescale(pts, (int64_t)stream->time_base.num * 90000, stream->time_base.den); + } + if (avContextTab[avContextIdx]->start_time != AV_NOPTS_VALUE) + { + pts -= 90000 * avContextTab[avContextIdx]->start_time / AV_TIME_BASE; + } + if (pts & 0x8000000000000000ull) + { + pts = INVALID_PTS_VALUE; + } + return pts; +} + +/* search for metatdata in context and stream + * and map it to our metadata. + */ + +static char *searchMeta(void *metadata, char *ourTag) +{ +#if LIBAVCODEC_VERSION_MAJOR < 54 + AVMetadataTag *tag = NULL; +#else + AVDictionaryEntry *tag = NULL; +#endif + int i = 0; + while (metadata_map[i] != NULL) + { + if (strcmp(ourTag, metadata_map[i]) == 0) + { +#if LIBAVCODEC_VERSION_MAJOR < 54 + while ((tag = av_metadata_get(metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) +#else + while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) +#endif + { + if (strcmp(tag->key, metadata_map[ i + 1 ]) == 0) + { + return tag->value; + } + } + } + i++; + } + return NULL; +} + +/* **************************** */ +/* Worker Thread */ +/* **************************** */ + +static void FFMPEGThread(Context_t *context) +{ + char threadname[17]; + strncpy(threadname, __func__, sizeof(threadname)); + threadname[16] = 0; + prctl(PR_SET_NAME, (unsigned long)&threadname); + AVPacket packet; + off_t lastSeek = -1; + int64_t lastPts = -1; + int64_t currentVideoPts = -1; + int64_t currentAudioPts = -1; + /* lastVideoDts and lastAudioDts + * used in isTSLiveMode + */ + int64_t lastVideoDts = -1; + int64_t lastAudioDts = -1; + int64_t showtime = 0; + int64_t bofcount = 0; + int32_t err = 0; + AudioVideoOut_t avOut; + g_context = context; + SwrContext *swr = NULL; + AVFrame *decoded_frame = NULL; + int32_t out_sample_rate = 44100; + int32_t out_channels = 2; + uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO; + uint32_t cAVIdx = 0; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) + Mpeg4P2Context mpeg4p2_context; + memset(&mpeg4p2_context, 0, sizeof(Mpeg4P2Context)); + AVBitStreamFilterContext *mpeg4p2_bsf_context = av_bitstream_filter_init("mpeg4_unpack_bframes"); +#endif +#ifdef HAVE_FLV2MPEG4_CONVERTER + Flv2Mpeg4Context flv2mpeg4_context; + memset(&flv2mpeg4_context, 0, sizeof(Flv2Mpeg4Context)); +#endif + ffmpeg_printf(10, "\n"); + while (context->playback->isCreationPhase) + { + ffmpeg_err("Thread waiting for end of init phase...\n"); + usleep(1000); + } + ffmpeg_printf(10, "Running!\n"); + int8_t isWaitingForFinish = 0; + while (context && context->playback && context->playback->isPlaying) + { + //IF MOVIE IS PAUSED, WAIT + if (context->playback->isPaused) + { + ffmpeg_printf(20, "paused\n"); + reset_finish_timeout(); + usleep(10000); + continue; + } + if (context->playback->isSeeking) + { + ffmpeg_printf(10, "seeking\n"); + reset_finish_timeout(); + usleep(10000); + continue; + } + getMutex(__FILE__, __FUNCTION__, __LINE__); + if (!context->playback || !context->playback->isPlaying) + { + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + if (!isWaitingForFinish) + { + reset_finish_timeout(); + } + continue; + } + if (do_seek_target_seconds || do_seek_target_bytes) + { + isWaitingForFinish = 0; + if (do_seek_target_seconds) + { + ffmpeg_printf(10, "seek_target_seconds[%lld]\n", seek_target_seconds); + uint32_t i = 0; + for (; i < IPTV_AV_CONTEXT_MAX_NUM; i += 1) + { + if (NULL != avContextTab[i]) + { + if (i == 1) + { + prev_seek_time_sec = seek_target_seconds; + } + if (avContextTab[i]->start_time != AV_NOPTS_VALUE) + { + seek_target_seconds += avContextTab[i]->start_time; + } + //av_seek_frame(avContextTab[i], -1, seek_target_seconds, 0); + avformat_seek_file(avContextTab[i], -1, INT64_MIN, seek_target_seconds, INT64_MAX, 0); + } + else + { + break; + } + } + reset_finish_timeout(); + } + else + { + container_ffmpeg_seek_bytes(seek_target_bytes); + } + do_seek_target_seconds = 0; + do_seek_target_bytes = 0; + restart_audio_resampling = 1; + currentVideoPts = -1; + currentAudioPts = -1; + latestPts = 0; + seek_target_flag = 0; + // flush streams + uint32_t i = 0; + for (i = 0; i < IPTV_AV_CONTEXT_MAX_NUM; i += 1) + { + if (NULL != avContextTab[i]) + { + if (i != 1) + { + wrapped_avcodec_flush_buffers(i); + } + } + else + { + break; + } + } +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) + mpeg4p2_context_reset(&mpeg4p2_context); + if (NULL != mpeg4p2_bsf_context) + { + av_bitstream_filter_close(mpeg4p2_bsf_context); + mpeg4p2_bsf_context = av_bitstream_filter_init("mpeg4_unpack_bframes"); + } +#endif +#ifdef HAVE_FLV2MPEG4_CONVERTER + flv2mpeg4_context_reset(&flv2mpeg4_context); +#endif + } + int ffmpegStatus = 0; + if (!isWaitingForFinish) + { + if (NULL != avContextTab[1]) + { + cAVIdx = currentVideoPts <= currentAudioPts ? 0 : 1; + if (1 == cAVIdx && prev_seek_time_sec >= 0) + { + avformat_seek_file(avContextTab[1], -1, (currentVideoPts / 90000) * AV_TIME_BASE - AV_TIME_BASE, (currentVideoPts / 90000) * AV_TIME_BASE, (currentVideoPts / 90000) * AV_TIME_BASE + AV_TIME_BASE, 0); + prev_seek_time_sec = -1; + wrapped_avcodec_flush_buffers(1); + } + } + else + { + cAVIdx = 0; + } + } + if (!isWaitingForFinish && (ffmpegStatus = av_read_frame(avContextTab[cAVIdx], &packet)) == 0) + { + int64_t pts = 0; + int64_t dts = 0; + Track_t *videoTrack = NULL; + Track_t *audioTrack = NULL; + Track_t *subtitleTrack = NULL; + int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id; + reset_finish_timeout(); + if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0) + { + ffmpeg_err("error getting video track\n"); + } + if (context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack) < 0) + { + ffmpeg_err("error getting audio track\n"); + } + if (context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack) < 0) + { + ffmpeg_err("error getting subtitle track\n"); + } + ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid); + if (videoTrack && (videoTrack->AVIdx == cAVIdx) && (videoTrack->Id == pid)) + { +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) + AVCodecContext *codec_context = videoTrack->avCodecCtx; + if (codec_context && codec_context->codec_id == AV_CODEC_ID_MPEG4 && NULL != mpeg4p2_bsf_context) + { + // should never happen, if it does print error and exit immediately, so we can easily spot it + if (filter_packet(mpeg4p2_bsf_context, codec_context, &packet) < 0) + { + ffmpeg_err("cannot filter mpegp2 packet\n"); + exit(1); + } + if (mpeg4p2_write_packet(context, &mpeg4p2_context, videoTrack, cAVIdx, ¤tVideoPts, &latestPts, &packet) < 0) + { + ffmpeg_err("cannot write mpeg4p2 packet\n"); + exit(1); + } + update_max_injected_pts(latestPts); + } + else +#endif +#ifdef HAVE_FLV2MPEG4_CONVERTER + if (get_codecpar(avContextTab[cAVIdx]->streams[packet.stream_index])->codec_id == AV_CODEC_ID_FLV1 && + 0 == memcmp(videoTrack->Encoding, "V_MPEG4", 7)) + { + flv2mpeg4_write_packet(context, &flv2mpeg4_context, videoTrack, cAVIdx, ¤tVideoPts, &latestPts, &packet); + update_max_injected_pts(latestPts); + } + else +#endif + { + uint8_t skipPacket = 0; + currentVideoPts = videoTrack->pts = pts = calcPts(cAVIdx, videoTrack->stream, packet.pts); + videoTrack->dts = dts = calcPts(cAVIdx, videoTrack->stream, packet.dts); + if ((currentVideoPts != INVALID_PTS_VALUE) && (currentVideoPts > latestPts)) + { + latestPts = currentVideoPts; + update_max_injected_pts(latestPts); + } + if (context->playback->isTSLiveMode) + { + if (dts != INVALID_PTS_VALUE) + { + if (dts > lastVideoDts) + { + lastVideoDts = dts; + } + else + { + // skip already injected VIDEO packet + ffmpeg_printf(200, "skip already injected VIDEO packet\n"); + skipPacket = 1; + } + } + else + { + // skip VIDEO packet with unknown DTS + ffmpeg_printf(200, "skip VIDEO packet with unknown DTS\n"); + skipPacket = 1; + } + } + if (skipPacket) + { + wrapped_packet_unref(&packet); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + continue; + } + ffmpeg_printf(200, "VideoTrack index = %d %lld\n", pid, currentVideoPts); + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.dts = dts; + avOut.extradata = videoTrack->extraData; + avOut.extralen = videoTrack->extraSize; + avOut.frameRate = videoTrack->frame_rate; + avOut.timeScale = videoTrack->TimeScale; + avOut.width = videoTrack->width; + avOut.height = videoTrack->height; + avOut.type = "video"; + if (avContextTab[cAVIdx]->iformat->flags & AVFMT_TS_DISCONT) + { + avOut.infoFlags = 1; // TS container + } + if (context->output->video->Write(context, &avOut) < 0) + { + ffmpeg_err("writing data to video device failed\n"); + } + } + } + else if (audioTrack && (audioTrack->AVIdx == cAVIdx) && (audioTrack->Id == pid)) + { + uint8_t skipPacket = 0; + currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, packet.pts); + dts = calcPts(cAVIdx, audioTrack->stream, packet.dts); + if ((currentAudioPts != INVALID_PTS_VALUE) && (currentAudioPts > latestPts) && (!videoTrack)) + { + latestPts = currentAudioPts; + update_max_injected_pts(latestPts); + } + if (context->playback->isTSLiveMode) + { + if (dts != INVALID_PTS_VALUE) + { + if (dts > lastAudioDts) + { + lastAudioDts = dts; + } + else + { + // skip already injected AUDIO packet + ffmpeg_printf(200, "skip already injected AUDIO packet\n"); + skipPacket = 1; + } + } + else + { + // skip AUDIO packet with unknown PTS + ffmpeg_printf(200, "skip AUDIO packet with unknown PTS\n"); + skipPacket = 1; + } + } + if (skipPacket) + { + wrapped_packet_unref(&packet); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + continue; + } + pcmPrivateData_t pcmExtradata; + pcmExtradata.channels = get_codecpar(audioTrack->stream)->channels; + pcmExtradata.bits_per_coded_sample = get_codecpar(audioTrack->stream)->bits_per_coded_sample; + pcmExtradata.sample_rate = get_codecpar(audioTrack->stream)->sample_rate; + pcmExtradata.bit_rate = get_codecpar(audioTrack->stream)->bit_rate; + pcmExtradata.ffmpeg_codec_id = get_codecpar(audioTrack->stream)->codec_id; + pcmExtradata.bResampling = restart_audio_resampling; + uint8_t *pAudioExtradata = get_codecpar(audioTrack->stream)->extradata; + uint32_t audioExtradataSize = get_codecpar(audioTrack->stream)->extradata_size; + ffmpeg_printf(200, "AudioTrack index = %d\n", pid); + if (audioTrack->inject_raw_pcm == 1) + { + ffmpeg_printf(200, "write audio raw pcm\n"); + restart_audio_resampling = 0; + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.extradata = (uint8_t *) &pcmExtradata; + avOut.extralen = sizeof(pcmExtradata); + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "audio"; + if (context->output->audio->Write(context, &avOut) < 0) + { + ffmpeg_err("(raw pcm) writing data to audio device failed\n"); + } + } + else if (audioTrack->inject_as_pcm == 1 && audioTrack->avCodecCtx) + { + AVCodecContext *c = audioTrack->avCodecCtx; + if (restart_audio_resampling) + { + restart_audio_resampling = 0; + if (swr) + { + swr_free(&swr); + swr = NULL; + } + if (decoded_frame) + { + wrapped_frame_free(&decoded_frame); + decoded_frame = NULL; + } + } +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) + while (packet.size > 0 || (!packet.size && !packet.data)) +#else + while (packet.size > 0) +#endif + { + if (do_seek_target_seconds || do_seek_target_bytes) + { + break; + } + if (!decoded_frame) + { + decoded_frame = wrapped_frame_alloc(); + if (!decoded_frame) + { + ffmpeg_err("out of memory\n"); + exit(1); + } + } + else + { + wrapped_frame_unref(decoded_frame); + } +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) + int ret = avcodec_send_packet(c, &packet); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + { + restart_audio_resampling = 1; + break; + } + if (ret >= 0) + { + packet.size = 0; + } + ret = avcodec_receive_frame(c, decoded_frame); + if (ret < 0) + { + if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + { + restart_audio_resampling = 1; + break; + } + else + { + continue; + } + } +#else + int32_t got_frame = 0; + int32_t len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &packet); + if (len < 0) + { + ffmpeg_err("avcodec_decode_audio4: %d\n", len); + break; + } + packet.data += len; + packet.size -= len; + if (!got_frame) + { + continue; + } +#endif + int32_t e = 0; + if (!swr) + { + if (insert_pcm_as_lpcm) + { + out_sample_rate = 48000; + } + else + { + int32_t rates[] = { 48000, 96000, 192000, 44100, 88200, 176400, 0 }; + int32_t *rate = rates; + int32_t in_rate = c->sample_rate; + while (*rate && ((*rate / in_rate) * in_rate != *rate) && (in_rate / *rate) * *rate != in_rate) + { + rate++; + } + out_sample_rate = *rate ? *rate : 44100; + } + swr = swr_alloc(); + out_channels = c->channels; + if (c->channel_layout == 0) + { + c->channel_layout = av_get_default_channel_layout(c->channels); + } + out_channel_layout = c->channel_layout; + uint8_t downmix = stereo_software_decoder && out_channels > 2 ? 1 : 0; +#ifdef __sh__ + // player2 won't play mono + if (out_channel_layout == AV_CH_LAYOUT_MONO) + { + downmix = 1; + } +#endif + if (downmix) + { + out_channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX; + out_channels = 2; + } + av_opt_set_int(swr, "in_channel_layout", c->channel_layout, 0); + av_opt_set_int(swr, "out_channel_layout", out_channel_layout, 0); + av_opt_set_int(swr, "in_sample_rate", c->sample_rate, 0); + av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0); + av_opt_set_int(swr, "in_sample_fmt", c->sample_fmt, 0); + av_opt_set_int(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + e = swr_init(swr); + if (e < 0) + { + ffmpeg_err("swr_init: %d (icl=%d ocl=%d isr=%d osr=%d isf=%d osf=%d\n", + -e, (int32_t)c->channel_layout, (int32_t)out_channel_layout, c->sample_rate, out_sample_rate, c->sample_fmt, AV_SAMPLE_FMT_S16); + swr_free(&swr); + swr = NULL; + } + } + uint8_t *output[8] = {NULL}; + int32_t in_samples = decoded_frame->nb_samples; + int32_t out_samples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP); + e = av_samples_alloc(&output[0], NULL, out_channels, out_samples, AV_SAMPLE_FMT_S16, 1); + if (e < 0) + { + ffmpeg_err("av_samples_alloc: %d\n", -e); + continue; + } + int64_t next_in_pts = av_rescale(av_frame_get_best_effort_timestamp(decoded_frame), + ((AVStream *) audioTrack->stream)->time_base.num * (int64_t)out_sample_rate * c->sample_rate, + ((AVStream *) audioTrack->stream)->time_base.den); + int64_t next_out_pts = av_rescale(swr_next_pts(swr, next_in_pts), + ((AVStream *) audioTrack->stream)->time_base.den, + ((AVStream *) audioTrack->stream)->time_base.num * (int64_t)out_sample_rate * c->sample_rate); + currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, next_out_pts); + out_samples = swr_convert(swr, &output[0], out_samples, (const uint8_t **) &decoded_frame->data[0], in_samples); + ////////////////////////////////////////////////////////////////////// + // Update pcmExtradata according to decode parameters + pcmExtradata.channels = av_get_channel_layout_nb_channels(out_channel_layout); + pcmExtradata.bits_per_coded_sample = 16; + pcmExtradata.sample_rate = out_sample_rate; + // The data described by the sample format is always in native-endian order +#ifdef WORDS_BIGENDIAN + pcmExtradata.ffmpeg_codec_id = AV_CODEC_ID_PCM_S16BE; +#else + pcmExtradata.ffmpeg_codec_id = AV_CODEC_ID_PCM_S16LE; +#endif + ////////////////////////////////////////////////////////////////////// + avOut.data = output[0]; + avOut.len = out_samples * sizeof(int16_t) * out_channels; + avOut.pts = pts; + avOut.extradata = (unsigned char *) &pcmExtradata; + avOut.extralen = sizeof(pcmExtradata); + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "audio"; + if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) + { + ffmpeg_err("writing data to audio device failed\n"); + } + av_freep(&output[0]); + } + } + else if (audioTrack->have_aacheader == 1) + { + ffmpeg_printf(200, "write audio aac\n"); + ffmpeg_printf(200, ">>>>>>> %x %x %x %x %x %x\n", packet.data[0], packet.data[1], packet.data[2], packet.data[3], packet.data[4], packet.data[5], packet.data[6]); + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.extradata = audioTrack->aacbuf; + avOut.extralen = audioTrack->aacbuflen; + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "audio"; + if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) + { + ffmpeg_err("(aac) writing data to audio device failed\n"); + } + } + else + { + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.extradata = pAudioExtradata; + avOut.extralen = audioExtradataSize; + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "audio"; + if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) + { + ffmpeg_err("writing data to audio device failed\n"); + } + } + } + else if (subtitleTrack && (subtitleTrack->Id == pid)) + { + int64_t duration = -1; + int64_t pts = calcPts(cAVIdx, subtitleTrack->stream, packet.pts); + AVStream *stream = subtitleTrack->stream; + if (packet.duration != 0) + { + // duration in milliseconds + duration = (int64_t)av_rescale(packet.duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); + } + else if (get_packet_duration(&packet) != 0 && get_packet_duration(&packet) != AV_NOPTS_VALUE) + { + // duration in milliseconds + duration = (int64_t)av_rescale(get_packet_duration(&packet), (int64_t)stream->time_base.num * 1000, stream->time_base.den); + } + if (duration > 0) + { + SubtitleOut_t subOut; + memset(&subOut, 0, sizeof(subOut)); + subOut.trackId = pid; + subOut.data = (uint8_t *)packet.data; + subOut.pts = pts; + subOut.durationMS = duration; + if (context->output->subtitle->Write(context, &subOut) < 0) + { + ffmpeg_err("writing data to teletext fifo failed\n"); + } + } + } + } + else + { + if (0 != ffmpegStatus) + { + static char errbuf[256]; + if (0 == av_strerror(ffmpegStatus, errbuf, sizeof(errbuf))) + { + /* In this way we inform user about error within the core + */ + printf("{\"log\":\"Frame read error: '%s'\"}\n", errbuf); + } + /* + if( ffmpegStatus == AVERROR(EAGAIN) ) + { + continue; + } + */ + ffmpegStatus = 0; + } + if (!is_finish_timeout() && !context->playback->isTSLiveMode) + { + isWaitingForFinish = 1; + update_finish_timeout(); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + usleep(100000); + continue; + } + else + { + uint8_t bEndProcess = 1; + if (context->playback->isTSLiveMode) + { + seek_target_bytes = 0; + do_seek_target_bytes = 1; + bEndProcess = 0; + } + else if (1 == context->playback->isLoopMode) + { + int64_t tmpLength = 0; + if (0 == container_ffmpeg_get_length(context, &tmpLength) && tmpLength > 0 && get_play_pts() > 0) + { +#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING + if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) + { + seek_target_bytes = 0; + do_seek_target_bytes = 1; + } + else +#endif + { + seek_target_seconds = 0; + do_seek_target_seconds = 1; + } + bEndProcess = 0; + context->output->Command(context, OUTPUT_CLEAR, NULL); + context->output->Command(context, OUTPUT_PLAY, NULL); + printf("{\"log\":\"Loop mode: jump to the start.\"}\n"); + } + } + // av_read_frame failed + ffmpeg_err("no data ->end of file reached ? \n"); + wrapped_packet_unref(&packet); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + if (bEndProcess) + { + break; // while + } + else + { + continue; + } + } + } + wrapped_packet_unref(&packet); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + } /* while */ + if (swr) + { + swr_free(&swr); + } + if (decoded_frame) + { + wrapped_frame_free(&decoded_frame); + } +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) + mpeg4p2_context_reset(&mpeg4p2_context); + if (NULL != mpeg4p2_bsf_context) + { + av_bitstream_filter_close(mpeg4p2_bsf_context); + } +#endif + hasPlayThreadStarted = 0; + context->playback->isPlaying = 0; + PlaybackDieNow(1); + ffmpeg_printf(10, "terminating\n"); +} + +/* **************************** */ +/* Container part for ffmpeg */ +/* **************************** */ + +static int32_t terminating = 0; +static int32_t interrupt_cb(void *ctx) +{ + PlaybackHandler_t *p = (PlaybackHandler_t *)ctx; + return p->abortRequested || PlaybackDieNow(0); +} + +#ifdef SAM_CUSTOM_IO +int SAM_ReadFunc(void *ptr, uint8_t *buffer, int lSize) +{ + size_t ret = fread((void *) buffer, (size_t) 1, (size_t) lSize, (FILE *)ptr); + return (int)ret; +} + +// whence: SEEK_SET, SEEK_CUR, SEEK_END (like fseek) and AVSEEK_SIZE +int64_t SAM_SeekFunc(void *ptr, int64_t pos, int whence) +{ + if (AVSEEK_SIZE == whence) + { + return -1; + } + int ret = fseeko((FILE *)ptr, (off_t)pos, whence); + if (0 == ret) + { + return (off_t)ftello((FILE *)ptr); + } + return ret; +} + +AVIOContext *container_ffmpeg_get_avio_context(char *filename, size_t avio_ctx_buffer_size) +{ + if (strstr(filename, "file://") == filename) + { + filename += 7; + } + FILE *pFile = fopen(filename, "rb"); + if (NULL == pFile) + { + return NULL; + } + AVIOContext *avio_ctx = NULL; + uint8_t *avio_ctx_buffer = NULL; + avio_ctx_buffer = av_malloc(avio_ctx_buffer_size); + if (!avio_ctx_buffer) + { + return NULL; + } + avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, pFile, &SAM_ReadFunc, NULL, &SAM_SeekFunc); + if (!avio_ctx) + { + return NULL; + } + return avio_ctx; +} +#endif + +int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int32_t AVIdx) +{ + int32_t err = 0; + AVInputFormat *fmt = NULL; + avContextTab[AVIdx] = avformat_alloc_context(); + avContextTab[AVIdx]->interrupt_callback.callback = interrupt_cb; + avContextTab[AVIdx]->interrupt_callback.opaque = context->playback; +#ifdef SAM_CUSTOM_IO + if (0 == strstr(filename, "://") || + 0 == strncmp(filename, "file://", 7)) + { + AVIOContext *avio_ctx = container_ffmpeg_get_avio_context(filename, 4096); + if (avio_ctx) + { + avContextTab[AVIdx]->pb = avio_ctx; + use_custom_io[AVIdx] = 1; + } + else + { + return cERR_CONTAINER_FFMPEG_OPEN; + } + } +#endif + AVDictionary **pavio_opts = NULL; + eRTMPProtoImplType rtmpProtoImplType = RTMP_NONE; + uint8_t numOfRTMPImpl = 0; + if (0 == strncmp(filename, "ffrtmp", 6)) + { + filename = filename + 2; + rtmpProtoImplType = RTMP_NATIVE; + } + if (1 == rtmp_proto_impl) + { + rtmpProtoImplType = RTMP_NATIVE; + } + else if (2 == rtmp_proto_impl) + { + rtmpProtoImplType = RTMP_LIBRTMP; + } + if (0 == strncmp(filename, "rtmp://", 7) || + 0 == strncmp(filename, "rtmpe://", 8) || + 0 == strncmp(filename, "rtmps://", 8) || + 0 == strncmp(filename, "rtmpt://", 8) || + 0 == strncmp(filename, "rtmpte://", 9) || + 0 == strncmp(filename, "rtmpts://", 9)) + { + /* At first we need to check which protocol + * implementations we have + */ + void *opaque = NULL; + const char *protoName = NULL; + uint8_t haveNativeProto = 0; + while (protoName = avio_enum_protocols(&opaque, 1)) + { + if (0 == strcmp("rtmp", protoName)) + { + ++numOfRTMPImpl; + } + else if (0 == strcmp("ffrtmp", protoName)) + { + // ffmpeg has patch to have both native and librtmp implementations + ++numOfRTMPImpl; + haveNativeProto = 2; + } + else if (0 == strncmp("rtmpts", protoName, 6)) + { + // rtmpts is only available in native implementation + // rtmpts is listed after rtmp + haveNativeProto = 1; + } + } + if (haveNativeProto > 0) + { + if (numOfRTMPImpl > 1) // we have both + { + if (rtmpProtoImplType == RTMP_NONE) + { + /* if we have both impl, we will prefer native + * unless uri contain param wich can be understandable + * only by librtmp + */ + if (strstr(filename, " token=") || + strstr(filename, " jtv=")) + { + rtmpProtoImplType = RTMP_LIBRTMP; + } + else + { + rtmpProtoImplType = RTMP_NATIVE; + } + } + } + else + { + rtmpProtoImplType = RTMP_NATIVE; + } + } + else + { + rtmpProtoImplType = RTMP_LIBRTMP; + } + if (RTMP_NATIVE == rtmpProtoImplType) + { + char *baseUri = strdup(filename); + char *token = NULL; + // check if uri have additional params + if ((token = strtok(baseUri, " ")) != NULL) + { + char *conn = malloc(strlen(filename)); + char *swfUrl = malloc(strlen(filename)); + char *swfVfy = malloc(strlen(filename)); + char *poseq, *key, *value; + conn[0] = '\0'; + swfUrl[0] = '\0'; + swfVfy[0] = '\0'; + token = NULL; + while ((token = strtok(token, " ")) != NULL) + { + if ((poseq = strchr(token, '=')) != NULL) + { + *poseq = '\0'; + key = token; + value = poseq + 1; + ffmpeg_printf(20, "rtmp_key = \"%s\", rtmp_value = \"%s\"\n", key, value); + /* translate librtmp connection parameters to ffmpeg ones routin provided by @mx3L + * + * librtmp parameters - https://rtmpdump.mplayerhq.hu/librtmp.3.html + * ffmpeg rtmp parameters - https://ffmpeg.org/ffmpeg-protocols.html#rtmp + */ + if (!strcasecmp(key, "app")) + { + av_dict_set(&avio_opts, "rtmp_app", value, 0); + } + else if (!strcasecmp(key, "conn")) + { + if (conn[0] != '\0') + { + strcat(conn, " "); + } + strcat(conn, value); + } + else if (!strcasecmp(key, "buffer")) + { + av_dict_set(&avio_opts, "rtmp_buffer", value, 0); + } + else if (!strcasecmp(key, "flashVer")) + { + av_dict_set(&avio_opts, "rtmp_flashver", value, 0); + } + else if (!strcasecmp(key, "live")) + { + av_dict_set(&avio_opts, "rtmp_live", value, 0); + } + else if (!strcasecmp(key, "pageUrl")) + { + av_dict_set(&avio_opts, "rtmp_pageurl", value, 0); + } + else if (!strcasecmp(key, "playpath")) + { + av_dict_set(&avio_opts, "rtmp_playpath", value, 0); + } + else if (!strcasecmp(key, "subscribe")) + { + av_dict_set(&avio_opts, "rtmp_subscribe", value, 0); + } + else if (!strcasecmp(key, "swfUrl")) + { + strcpy(swfUrl, value); + } + // ffmpeg expects this value to contain url to player swf + // not a 1|0|TRUE like librtmp + else if (!strcasecmp(key, "swfVfy")) + { + strcpy(swfVfy, value); + } + else if (!strcasecmp(key, "tcUrl")) + { + av_dict_set(&avio_opts, "rtmp_tcurl", value, 0); + } + // timeout is ment for incoming connections + else if (!strcasecmp(key, "timeout")) + { + } + else + { + // threat as direct options + // for example rtmp_swfhash, rtmp_swfsize + av_dict_set(&avio_opts, key, value, 0); + } + } + token = NULL; + } + if (conn[0] != '\0') + { + av_dict_set(&avio_opts, "rtmp_conn", conn, 0); + } + free(conn); + if (swfUrl[0] != '\0') + { + if (swfVfy[0] == '1' || !strncasecmp(swfVfy, "true", 4)) + { + av_dict_set(&avio_opts, "rtmp_swfverify", swfUrl, 0); + } + else + { + av_dict_set(&avio_opts, "rtmp_swfurl", swfUrl, 0); + } + } + free(swfUrl); + free(swfVfy); + } + if (2 == haveNativeProto) + { + filename = malloc(strlen(baseUri) + 2 + 1); + strncpy(filename, "ff", 2); + strcpy(filename + 2, baseUri); + free(baseUri); + // memory leak, only once, so does not matter + } + else + { + filename = baseUri; + // memory leak, only once, so does not matter + } + } + } + else if (0 == strncmp(filename, "http://", 7) || + 0 == strncmp(filename, "https://", 8)) + { + av_dict_set(&avio_opts, "timeout", "20000000", 0); //20sec + av_dict_set(&avio_opts, "reconnect", "1", 0); + if (context->playback->isTSLiveMode) // special mode for live TS stream with skip packet + { + av_dict_set(&avio_opts, "seekable", "0", 0); + av_dict_set(&avio_opts, "reconnect_at_eof", "1", 0); + av_dict_set(&avio_opts, "reconnect_streamed", "1", 0); + } + } + pavio_opts = &avio_opts; + if ((err = avformat_open_input(&avContextTab[AVIdx], filename, fmt, pavio_opts)) != 0) + { + if (rtmp_proto_impl == 0 && //err == AVERROR_UNKNOWN && + rtmpProtoImplType == RTMP_NATIVE && + numOfRTMPImpl > 1) + { + // retry with librtmp + err = avformat_open_input(&avContextTab[AVIdx], filename + 2, fmt, pavio_opts); + // filename2 - another memory leak, and also only once, so does not matter + } + if (err != 0) + { + char error[512]; + ffmpeg_err("avformat_open_input failed %d (%s)\n", err, filename); + av_strerror(err, error, 512); + fprintf(stderr, "{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err); + if (avio_opts != NULL) + { + av_dict_free(&avio_opts); + } + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_OPEN; + } + } + avContextTab[AVIdx]->iformat->flags |= AVFMT_SEEK_TO_PTS; + avContextTab[AVIdx]->flags = AVFMT_FLAG_GENPTS; + if (context->playback->noprobe) + { + wrapped_set_max_analyze_duration(avContextTab[AVIdx], 1); + } + ffmpeg_printf(20, "find_streaminfo\n"); + if (avformat_find_stream_info(avContextTab[AVIdx], NULL) < 0) + { + ffmpeg_err("Error avformat_find_stream_info\n"); + } +//for buffered io + if (avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL && !context->playback->isTSLiveMode) + { + ffmpeg_real_read_org = avContextTab[AVIdx]->pb->read_packet; + if (0 == AVIdx && strstr(filename, "://") != 0 && + strncmp(filename, "file://", 7) != 0) + { + if (ffmpeg_buf_size > 0 && ffmpeg_buf_size > FILLBUFDIFF + FILLBUFPAKET) + { + if (avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL) + { + ffmpeg_buf = av_malloc(ffmpeg_buf_size); + if (ffmpeg_buf != NULL) + { + ffmpeg_printf(10, "buffer size=%d\n", ffmpeg_buf_size); + ffmpeg_read_org = avContextTab[AVIdx]->pb->read_packet; + avContextTab[AVIdx]->pb->read_packet = ffmpeg_read; + ffmpeg_seek_org = avContextTab[AVIdx]->pb->seek; + avContextTab[AVIdx]->pb->seek = ffmpeg_seek; + ffmpeg_buf_read = ffmpeg_buf; + ffmpeg_buf_write = ffmpeg_buf; + //fill buffer + ffmpeg_filler(context, -1, NULL, 0); + ffmpeg_start_fillerTHREAD(context); + } + } + } + } + else if (progressive_playback) + { + avContextTab[AVIdx]->pb->read_packet = ffmpeg_read_wrapper; + } + } +//for buffered io (end) + return 0; +} + +int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames) +{ + int32_t err = 0; + ffmpeg_printf(10, ">\n"); + if (playFilesNames == NULL) + { + ffmpeg_err("playFilesNames NULL\n"); + return cERR_CONTAINER_FFMPEG_NULL; + } + if (playFilesNames->szFirstFile == NULL) + { + ffmpeg_err("playFilesNames->szFirstFile NULL\n"); + return cERR_CONTAINER_FFMPEG_NULL; + } + if (context == NULL) + { + ffmpeg_err("context NULL\n"); + return cERR_CONTAINER_FFMPEG_NULL; + } + ffmpeg_printf(10, "filename %s\n", playFilesNames->szFirstFile); + if (playFilesNames->szSecondFile) + { + ffmpeg_printf(10, "second filename %s\n", playFilesNames->szSecondFile); + } + if (isContainerRunning) + { + ffmpeg_err("ups already running?\n"); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_RUNNING; + } + /* initialize ffmpeg */ + avcodec_register_all(); + av_register_all(); + avformat_network_init(); + // SULGE DEBUG ENABLED + // make ffmpeg silen + //av_log_set_level( AV_LOG_DEBUG ); + av_log_set_callback(ffmpeg_silen_callback); + context->playback->abortRequested = 0; + int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, 0); + if (0 != res) + { + return res; + } + if (playFilesNames->szSecondFile) + { + res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, 1); + } + if (0 != res) + { + return res; + } + terminating = 0; + latestPts = 0; + isContainerRunning = 1; + res = container_ffmpeg_update_tracks(context, playFilesNames->szFirstFile, 1); + return res; +} + +int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32_t initial) +{ + Track_t *audioTrack = NULL; + Track_t *subtitleTrack = NULL; + if (terminating) + { + return cERR_CONTAINER_FFMPEG_NO_ERROR; + } + if (initial && context->manager->subtitle) + { + context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack); + } + if (context->manager->audio) + { + context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + } + if (context->manager->video) + { + context->manager->video->Command(context, MANAGER_INIT_UPDATE, NULL); + } + if (context->manager->audio) + { + context->manager->audio->Command(context, MANAGER_INIT_UPDATE, NULL); + } +#if 0 + if (context->manager->subtitle) + { + context->manager->subtitle->Command(context, MANAGER_INIT_UPDATE, NULL); + } +#endif + ffmpeg_printf(20, "dump format\n"); + av_dump_format(avContextTab[0], 0, filename, 0); + uint32_t cAVIdx = 0; + for (cAVIdx = 0; cAVIdx < IPTV_AV_CONTEXT_MAX_NUM; cAVIdx += 1) + { + if (NULL == avContextTab[cAVIdx]) + { + break; + } + AVFormatContext *avContext = avContextTab[cAVIdx]; + uint32_t *stream_index = NULL; + uint32_t nb_stream_indexes = 0; + ffmpeg_printf(1, "cAVIdx[%d]: number of streams: %d\n", cAVIdx, avContext->nb_streams); + if (avContext->nb_programs > 0) + { + uint32_t n = 0; + ffmpeg_printf(1, "cAVIdx[%d]: stream with multi programs: num of programs %d\n", cAVIdx, avContext->nb_programs); + for (n = 0; n < avContext->nb_programs && (0 == nb_stream_indexes || stream_index == NULL); n++) + { + AVProgram *p = avContext->programs[n]; + if (p->nb_stream_indexes) + { + if (g_sel_program_id > 0) + { + if (g_sel_program_id == p->id) + { + stream_index = p->stream_index; + nb_stream_indexes = p->nb_stream_indexes; + ffmpeg_printf(1, "cAVIdx[%d]: select PROGRAM ID: %d\n", cAVIdx, (int32_t)p->id); + break; + } + } + else + { + uint32_t m = 0; + for (m = 0; m < p->nb_stream_indexes; m++) + { + AVStream *s = avContext->streams[p->stream_index[m]]; + if (get_codecpar(s)->codec_type == AVMEDIA_TYPE_VIDEO && get_codecpar(s)->width > 0) + { + ffmpeg_printf(1, "cAVIdx[%d]: PROGRAM ID: %d, width [%d]\n", cAVIdx, (int32_t)p->id, (int32_t)get_codecpar(s)->width); + stream_index = p->stream_index; + nb_stream_indexes = p->nb_stream_indexes; + break; + } + } + } + } + } + } + int32_t n = 0; + for (n = 0; n < avContext->nb_streams; n++) + { + Track_t track; + AVStream *stream = avContext->streams[n]; + int32_t version = 0; + char *encoding = NULL; + if (nb_stream_indexes > 0 && stream_index != NULL) + { + uint32_t isStreamFromSelProg = 0; + uint32_t m = 0; + for (m = 0; m < nb_stream_indexes; m++) + { + if (n == stream_index[m]) + { + isStreamFromSelProg = 1; + break; + } + } + if (!isStreamFromSelProg) + continue; // skip this stream + } + encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \ + (uint8_t *)get_codecpar(stream)->extradata, \ + (int)get_codecpar(stream)->extradata_size, \ + (int)get_codecpar(stream)->profile, &version); + if (encoding != NULL && !strncmp(encoding, "A_IPCM", 6) && insert_pcm_as_lpcm) + { + encoding = "A_LPCM"; + } + if (encoding != NULL) + { + ffmpeg_printf(1, "%d. encoding = %s - version %d\n", n, encoding, version); + } + if (!stream->id) + { + stream->id = n; + } + /* some values in track are unset and therefor copyTrack segfaults. + * so set it by default to NULL! + */ + memset(&track, 0, sizeof(track)); + track.AVIdx = cAVIdx; + switch (get_codecpar(stream)->codec_type) + { + case AVMEDIA_TYPE_VIDEO: + ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type); + if (encoding != NULL) + { + track.type = eTypeES; + track.version = version; + track.width = get_codecpar(stream)->width; + track.height = get_codecpar(stream)->height; + /* We will return here PAR (Pixel Aspect Ratio) client need to calculate DAR(Display Aspect Ratio) + * example: PAR 64:45 DAR 16:9 + * Resolution 720x576 + * Display aspect ratio = (720*64)/(576*45) = 16/9 + * 0:1 is the value for invalid/unset aspect ratio -> https://trac.ffmpeg.org/ticket/3798 + */ + track.aspect_ratio_num = stream->sample_aspect_ratio.num; + track.aspect_ratio_den = stream->sample_aspect_ratio.den; + if (0 == track.aspect_ratio_num || 0 == track.aspect_ratio_den) + { + track.aspect_ratio_num = get_codecpar(stream)->sample_aspect_ratio.num; + track.aspect_ratio_den = get_codecpar(stream)->sample_aspect_ratio.den; + } + track.extraData = get_codecpar(stream)->extradata; + track.extraSize = get_codecpar(stream)->extradata_size; + track.aacbuf = 0; + track.have_aacheader = -1; + AVRational rateRational = get_frame_rate(stream); + if (rateRational.den != 0) + { + track.frame_rate = (uint32_t)(1000 * (int64_t)(rateRational.num) / (int64_t)(rateRational.den)); + } + /* fixme: revise this */ + if (track.frame_rate < 23970) + { + track.TimeScale = 1001; + } + else + { + track.TimeScale = 1000; + } + ffmpeg_printf(10, "bit_rate [%d]\n", get_codecpar(stream)->bit_rate); + ffmpeg_printf(10, "time_base.den [%d]\n", stream->time_base.den); + ffmpeg_printf(10, "time_base.num [%d]\n", stream->time_base.num); + ffmpeg_printf(10, "width [%d]\n", get_codecpar(stream)->width); + ffmpeg_printf(10, "height [%d]\n", get_codecpar(stream)->height); + ffmpeg_printf(10, "frame_rate num [%d]\n", rateRational.num); + ffmpeg_printf(10, "frame_rate den [%d]\n", rateRational.den); + ffmpeg_printf(10, "frame_rate [%u]\n", track.frame_rate); + ffmpeg_printf(10, "TimeScale [%d]\n", track.TimeScale); + track.Name = "und"; + track.Encoding = encoding; + track.stream = stream; + track.Id = ((AVStream *)(track.stream))->id; + track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); + if (stream->duration == AV_NOPTS_VALUE || 0 == strncmp(avContext->iformat->name, "dash", 4)) + { + ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); + track.duration = (int64_t) avContext->duration / 1000; + } + if (context->manager->video) + { + if (get_codecpar(stream)->codec_id == AV_CODEC_ID_MPEG4) + { + track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream); + } + ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track VIDEO\n"); + if (context->manager->video->Command(context, MANAGER_ADD, &track) < 0) + { + /* konfetti: fixme: is this a reason to return with error? */ + ffmpeg_err("failed to add track %d\n", n); + } + } + } + else + { + ffmpeg_err("codec type video but codec unknown %d\n", get_codecpar(stream)->codec_id); + } + break; + case AVMEDIA_TYPE_AUDIO: + ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n", get_codecpar(stream)->codec_type); + if (encoding != NULL) + { + AVDictionaryEntry *lang; + track.type = eTypeES; + lang = av_dict_get(stream->metadata, "language", NULL, 0); + track.Name = lang ? lang->value : "und"; + ffmpeg_printf(10, "Language %s\n", track.Name); + track.Encoding = encoding; + track.stream = stream; + track.Id = ((AVStream *)(track.stream))->id; + track.aacbuf = 0; + track.have_aacheader = -1; + track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); + if (stream->duration == AV_NOPTS_VALUE) + { + ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); + track.duration = (int64_t) avContext->duration / 1000; + } + if (!strncmp(encoding, "A_IPCM", 6) || !strncmp(encoding, "A_LPCM", 6)) + { + track.inject_as_pcm = 1; + track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream); + if (track.avCodecCtx) + { + ffmpeg_printf(10, " Handle inject_as_pcm = %d\n", track.inject_as_pcm); + AVCodec *codec = avcodec_find_decoder(get_codecpar(stream)->codec_id); + int errorCode = avcodec_open2(track.avCodecCtx, codec, NULL); + if (codec != NULL && !errorCode) + { + ffmpeg_printf(10, "AVCODEC__INIT__SUCCESS\n"); + } + else + { + ffmpeg_printf(10, "AVCODEC__INIT__FAILED error[%d]\n", errorCode); + } + } + } + else if (!strncmp(encoding, "A_PCM", 5)) + { + track.inject_raw_pcm = 1; + } + else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC_LATM) + { + const char marker[] = "LATM"; + track.aacbuflen = sizeof(marker) / sizeof(char); + track.aacbuf = malloc(track.aacbuflen); + memcpy(track.aacbuf, marker, track.aacbuflen); + ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM no extradata ACC header should be available in each frame\n"); + track.have_aacheader = 1; + } + else if (!strncmp(encoding, "A_AAC_LATM", 10)) + { + ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM extradata will be used in aac writter\n"); + } + else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC) + { + if (0 == strncmp(avContext->iformat->name, "mpegts", 6) || + 0 == strncmp(avContext->iformat->name, "hls,", 4)) + { + const char marker[] = "ADTS"; + track.aacbuflen = sizeof(marker) / sizeof(char); + track.aacbuf = malloc(track.aacbuflen); + memcpy(track.aacbuf, marker, track.aacbuflen); + ffmpeg_printf(10, "AV_CODEC_ID_AAC no extradata ACC header should be available in each frame\n"); + track.have_aacheader = 1; + } + else + { + ffmpeg_printf(10, "Create AAC ExtraData\n"); + ffmpeg_printf(10, "get_codecpar(stream)->extradata_size %d\n", get_codecpar(stream)->extradata_size); + //Hexdump(get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size); + /* extradata: + 13 10 56 e5 9d 48 00 (anderen cops) + object_type: 00010 2 = LC + sample_rate: 011 0 6 = 24000 + chan_config: 0010 2 = Stereo + 000 0 + 1010110 111 = 0x2b7 + 00101 = SBR + 1 + 0011 = 48000 + 101 01001000 = 0x548 + ps = 0 + 0000000 + */ + int32_t object_type = 2; // LC + int32_t sample_index = aac_get_sample_rate_index(get_codecpar(stream)->sample_rate); + int32_t chan_config = get_codecpar(stream)->channels - 1; + ffmpeg_printf(1, "aac object_type %d\n", object_type); + ffmpeg_printf(1, "aac sample_index %d\n", sample_index); + ffmpeg_printf(1, "aac chan_config %d\n", chan_config); + if (get_codecpar(stream)->extradata_size >= 2) + { + MPEG4AudioConfig m4ac; + int off = avpriv_mpeg4audio_get_config(&m4ac, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size * 8, 1); + if (off >= 0) + { + object_type = m4ac.object_type; + sample_index = m4ac.sampling_index; + if (sample_index == 0x0f) + { + sample_index = aac_get_sample_rate_index(m4ac.sample_rate); + } + chan_config = m4ac.chan_config; + } + } + ffmpeg_printf(1, "aac object_type %d\n", object_type); + ffmpeg_printf(1, "aac sample_index %d\n", sample_index); + ffmpeg_printf(1, "aac chan_config %d\n", chan_config); + // https://wiki.multimedia.cx/index.php/ADTS + object_type -= 1; //ADTS - profile, the MPEG-4 Audio Object Type minus 1 + track.aacbuflen = AAC_HEADER_LENGTH; + track.aacbuf = malloc(8); + track.aacbuf[0] = 0xFF; + track.aacbuf[1] = 0xF1; + //track.aacbuf[1] |=0x8; + track.aacbuf[2] = ((object_type & 0x03) << 6) | (sample_index << 2) | ((chan_config >> 2) & 0x01); + track.aacbuf[3] = (chan_config & 0x03) << 6; + //track.aacbuf[3]|= 0x10; + track.aacbuf[4] = 0x00; + track.aacbuf[5] = 0x1F; + track.aacbuf[6] = 0xFC; + //printf("AAC_HEADER -> "); + //Hexdump(track.aacbuf,7); + track.have_aacheader = 1; + } + /* + else + { + ffmpeg_err("AV_CODEC_ID_AAC extradata not available\n"); + } + */ + } + else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV1 + || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV2 + || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAPRO + || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMALOSSLESS) //if (get_codecpar(stream)->extradata_size > 0) + { + ffmpeg_printf(10, "Create WMA ExtraData\n"); + uint16_t channels = get_codecpar(stream)->channels; + uint32_t rate = get_codecpar(stream)->sample_rate; + uint32_t bitrate = get_codecpar(stream)->bit_rate; + uint16_t block_align = get_codecpar(stream)->block_align; + uint16_t depth = get_codecpar(stream)->bits_per_coded_sample; + uint32_t codec_data_size = get_codecpar(stream)->extradata_size; + uint8_t *codec_data_pointer = get_codecpar(stream)->extradata; + // type_specific_data +#define WMA_VERSION_1 0x160 +#define WMA_VERSION_2_9 0x161 +#define WMA_VERSION_9_PRO 0x162 +#define WMA_LOSSLESS 0x163 + uint16_t codec_id = 0; + switch (get_codecpar(stream)->codec_id) + { + //TODO: What code for lossless ? + case AV_CODEC_ID_WMALOSSLESS: + codec_id = WMA_LOSSLESS; + break; + case AV_CODEC_ID_WMAPRO: + codec_id = WMA_VERSION_9_PRO; + break; + case AV_CODEC_ID_WMAV2: + codec_id = WMA_VERSION_2_9 ; + break; + case AV_CODEC_ID_WMAV1: + default: + codec_id = WMA_VERSION_1; + break; + } +#ifdef __sh__ + track.aacbuflen = 104 + get_codecpar(stream)->extradata_size; + track.aacbuf = malloc(track.aacbuflen); + memset(track.aacbuf, 0, track.aacbuflen); + uint8_t ASF_Stream_Properties_Object[16] = + {0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}; + memcpy(track.aacbuf + 0, ASF_Stream_Properties_Object, 16); // ASF_Stream_Properties_Object + memcpy(track.aacbuf + 16, &track.aacbuflen, 4); //FrameDateLength + uint32_t sizehi = 0; + memcpy(track.aacbuf + 20, &sizehi, 4); // sizehi (not used) + uint8_t ASF_Audio_Media[16] = + {0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B}; + memcpy(track.aacbuf + 24, ASF_Audio_Media, 16); //ASF_Audio_Media + uint8_t ASF_Audio_Spread[16] = + {0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20}; + memcpy(track.aacbuf + 40, ASF_Audio_Spread, 16); //ASF_Audio_Spread + memset(track.aacbuf + 56, 0, 4); // time_offset (not used) + memset(track.aacbuf + 60, 0, 4); // time_offset_hi (not used) + uint8_t type_specific_data_length = 18 + get_codecpar(stream)->extradata_size; + memcpy(track.aacbuf + 64, &type_specific_data_length, 4); //type_specific_data_length + uint8_t error_correction_data_length = 8; + memcpy(track.aacbuf + 68, &error_correction_data_length, 4); //error_correction_data_length + uint16_t flags = 1; // stream_number + memcpy(track.aacbuf + 72, &flags, 2); //flags + uint32_t reserved = 0; + memcpy(track.aacbuf + 74, &reserved, 4); // reserved + memcpy(track.aacbuf + 78, &codec_id, 2); //codec_id + uint16_t number_of_channels = get_codecpar(stream)->channels; + memcpy(track.aacbuf + 80, &number_of_channels, 2); //number_of_channels + uint32_t samples_per_second = get_codecpar(stream)->sample_rate; + ffmpeg_printf(1, "samples_per_second = %d\n", samples_per_second); + memcpy(track.aacbuf + 82, &samples_per_second, 4); //samples_per_second + uint32_t average_number_of_bytes_per_second = get_codecpar(stream)->bit_rate / 8; + ffmpeg_printf(1, "average_number_of_bytes_per_second = %d\n", average_number_of_bytes_per_second); + memcpy(track.aacbuf + 86, &average_number_of_bytes_per_second, 4); //average_number_of_bytes_per_second + uint16_t block_alignment = get_codecpar(stream)->block_align; + ffmpeg_printf(1, "block_alignment = %d\n", block_alignment); + memcpy(track.aacbuf + 90, &block_alignment, 2); //block_alignment +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) + enum AVSampleFormat sample_fmt = get_codecpar(stream)->format; +#else + enum AVSampleFormat sample_fmt = get_codecpar(stream)->sample_fmt; +#endif + uint16_t bits_per_sample = sample_fmt >= 0 ? (sample_fmt + 1) * 8 : 8; + ffmpeg_printf(1, "bits_per_sample = %d (%d)\n", bits_per_sample, sample_fmt); + memcpy(track.aacbuf + 92, &bits_per_sample, 2); //bits_per_sample + memcpy(track.aacbuf + 94, &get_codecpar(stream)->extradata_size, 2); //bits_per_sample + memcpy(track.aacbuf + 96, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size); +#else + track.aacbuflen = 18 + get_codecpar(stream)->extradata_size; + track.aacbuf = malloc(track.aacbuflen); + memset(track.aacbuf, 0, track.aacbuflen); + uint8_t *data = track.aacbuf; + /* codec tag */ + *(data++) = codec_id & 0xff; + *(data++) = (codec_id >> 8) & 0xff; + /* channels */ + *(data++) = channels & 0xff; + *(data++) = (channels >> 8) & 0xff; + /* sample rate */ + *(data++) = rate & 0xff; + *(data++) = (rate >> 8) & 0xff; + *(data++) = (rate >> 16) & 0xff; + *(data++) = (rate >> 24) & 0xff; + /* byte rate */ + bitrate /= 8; + *(data++) = bitrate & 0xff; + *(data++) = (bitrate >> 8) & 0xff; + *(data++) = (bitrate >> 16) & 0xff; + *(data++) = (bitrate >> 24) & 0xff; + /* block align */ + *(data++) = block_align & 0xff; + *(data++) = (block_align >> 8) & 0xff; + /* word size */ + *(data++) = depth & 0xff; + *(data++) = (depth >> 8) & 0xff; + /* codec data size */ + *(data++) = codec_data_size & 0xff; + *(data++) = (codec_data_size >> 8) & 0xff; + memcpy(data, codec_data_pointer, codec_data_size); +#endif + ffmpeg_printf(1, "aacbuf:\n"); + //Hexdump(track.aacbuf, track.aacbuflen); + //ffmpeg_printf(1, "priv_data:\n"); + //Hexdump(get_codecpar(stream)->priv_data, track.aacbuflen); + track.have_aacheader = 1; + } + if (context->manager->audio) + { + ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track AUDIO\n"); + if (context->manager->audio->Command(context, MANAGER_ADD, &track) < 0) + { + /* konfetti: fixme: is this a reason to return with error? */ + ffmpeg_err("failed to add track %d\n", n); + } + } + } + else //encoding != NULL + { + ffmpeg_err("codec type audio but codec unknown %d\n", get_codecpar(stream)->codec_id); + } + break; + case AVMEDIA_TYPE_SUBTITLE: + { + if (get_codecpar(stream)->codec_id != AV_CODEC_ID_SSA && +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100) + get_codecpar(stream)->codec_id != AV_CODEC_ID_ASS && +#endif + get_codecpar(stream)->codec_id != AV_CODEC_ID_SUBRIP && + get_codecpar(stream)->codec_id != AV_CODEC_ID_TEXT && + get_codecpar(stream)->codec_id != AV_CODEC_ID_SRT) + { + ffmpeg_printf(10, "subtitle with not supported codec codec_id[%u]\n", (uint32_t)get_codecpar(stream)->codec_id); + } + else if (initial && context->manager->subtitle) + { + AVDictionaryEntry *lang = NULL; + memset(&track, 0, sizeof(track)); + ffmpeg_printf(10, "CODEC_TYPE_SUBTITLE %d\n", get_codecpar(stream)->codec_type); + lang = av_dict_get(stream->metadata, "language", NULL, 0); + track.Name = lang ? lang->value : "und"; + ffmpeg_printf(10, "Language %s\n", track.Name); + track.Encoding = encoding; + track.stream = stream; + track.Id = ((AVStream *)(track.stream))->id; + track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); + if (stream->duration == AV_NOPTS_VALUE) + { + ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); + track.duration = (int64_t) avContext->duration / 1000; + } + track.extraData = get_codecpar(stream)->extradata; + track.extraSize = get_codecpar(stream)->extradata_size; + ffmpeg_printf(1, "subtitle codec %d\n", get_codecpar(stream)->codec_id); + ffmpeg_printf(1, "subtitle width %d\n", get_codecpar(stream)->width); + ffmpeg_printf(1, "subtitle height %d\n", get_codecpar(stream)->height); + ffmpeg_printf(1, "subtitle stream %p\n", stream); + ffmpeg_printf(10, "FOUND SUBTITLE %s\n", track.Name); + if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0) + { + ffmpeg_err("failed to add subtitle track %d\n", n); + } + } + break; + } + case AVMEDIA_TYPE_UNKNOWN: + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_ATTACHMENT: + case AVMEDIA_TYPE_NB: + default: + ffmpeg_err("not handled or unknown codec_type %d\n", get_codecpar(stream)->codec_type); + break; + } + } /* for */ + } + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_ffmpeg_play(Context_t *context) +{ + int32_t error = 0; + int32_t ret = 0; + pthread_attr_t attr; + ffmpeg_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) + { + ffmpeg_printf(10, "is Playing\n"); + } + else + { + ffmpeg_printf(10, "is NOT Playing\n"); + } + if (hasPlayThreadStarted == 0) + { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if ((error = pthread_create(&PlayThread, &attr, (void *)&FFMPEGThread, context)) != 0) + { + ffmpeg_printf(10, "Error creating thread, error:%d:%s\n", error, strerror(error)); + hasPlayThreadStarted = 0; + ret = cERR_CONTAINER_FFMPEG_ERR; + } + else + { + ffmpeg_printf(10, "Created thread\n"); + hasPlayThreadStarted = 1; + } + } + else + { + ffmpeg_printf(10, "A thread already exists!\n"); + ret = cERR_CONTAINER_FFMPEG_ERR; + } + ffmpeg_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t container_ffmpeg_stop(Context_t *context) +{ + int32_t ret = cERR_CONTAINER_FFMPEG_NO_ERROR; + int32_t wait_time = 10; // we give 1s to close otherwise we will force close + ffmpeg_printf(10, "\n"); + if (!isContainerRunning) + { + ffmpeg_err("Container not running\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + if (context->playback) + { + context->playback->isPlaying = 0; + } + while ((hasPlayThreadStarted != 0) && (--wait_time) > 0) + { + ffmpeg_printf(10, "Waiting for ffmpeg thread to terminate itself, will try another %d times\n", wait_time); + usleep(100000); + } + if (wait_time == 0) + { + /* force close */ + ffmpeg_err("Timeout waiting for thread!\n"); + ret = cERR_CONTAINER_FFMPEG_ERR; + /* to speed up close - we are in separate process for the moment this process will + * be closed and whole resources will be free by the system + */ + return ret; + } + hasPlayThreadStarted = 0; + terminating = 1; + getMutex(__FILE__, __FUNCTION__, __LINE__); + free_all_stored_avcodec_context(); + uint32_t i = 0; + for (i = 0; i < IPTV_AV_CONTEXT_MAX_NUM; i += 1) + { + if (NULL != avContextTab[i]) + { + if (0 != use_custom_io[i]) + { + /* + * Free custom IO independently to avoid segfault/bus error + * avformat_close_input do not expect custom io, so it try + * to release incorrectly + */ + av_freep(&(avContextTab[i]->pb->buffer)); + av_freep(&(avContextTab[i]->pb)); + use_custom_io[i] = 0; + } + avformat_close_input(&avContextTab[i]); + avContextTab[i] = NULL; + } + else + { + break; + } + } + if (avio_opts != NULL) + { + av_dict_free(&avio_opts); + } + isContainerRunning = 0; + avformat_network_deinit(); + ffmpeg_buf_free(); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + ffmpeg_printf(10, "ret %d\n", ret); + return ret; +} + +static int32_t container_ffmpeg_seek_bytes(off_t pos) +{ + int32_t flag = AVSEEK_FLAG_BYTE; + off_t current_pos = avio_tell(avContextTab[0]->pb); + ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos); + if (current_pos > pos) + { + flag |= AVSEEK_FLAG_BACKWARD; + } + if (avformat_seek_file(avContextTab[0], -1, INT64_MIN, pos, INT64_MAX, flag) < 0) + { + ffmpeg_err("Error seeking\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + ffmpeg_printf(30, "current_pos after seek %lld\n", avio_tell(avContextTab[0]->pb)); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +/* seeking relative to a given byteposition N seconds ->for reverse playback needed */ +static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec) +{ + Track_t *videoTrack = NULL; + Track_t *audioTrack = NULL; + Track_t *current = NULL; + seek_target_flag = 0; + ffmpeg_printf(10, "seeking %f sec relativ to %lld\n", sec, pos); + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); + context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (videoTrack != NULL) + { + current = videoTrack; + } + else if (audioTrack != NULL) + { + current = audioTrack; + } + if (current == NULL) + { + ffmpeg_err("no track avaibale to seek\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + if (pos == -1) + { + pos = avio_tell(avContextTab[0]->pb); + } + if (pts == -1) + { + pts = current->pts; + } + if (sec < 0) + { + seek_target_flag |= AVSEEK_FLAG_BACKWARD; + } + ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags); +#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING + if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) + { + if (avContextTab[0]->bit_rate) + { + sec *= avContextTab[0]->bit_rate / 8; + ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate); + } + else + { + sec *= 180000; + } + pos += sec; + if (pos < 0) + { + ffmpeg_err("end of file reached\n"); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_END_OF_FILE; + } + ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %f\n", pos, sec); + seek_target_bytes = pos; + do_seek_target_bytes = 1; + return pos; + } + else +#endif + { + sec += pts / 90000; + if (sec < 0) + { + sec = 0; + } + ffmpeg_printf(10, "2. seeking to position %f sec ->time base %f %d\n", sec, av_q2d(((AVStream *) current->stream)->time_base), AV_TIME_BASE); + seek_target_seconds = sec * AV_TIME_BASE; + do_seek_target_seconds = 1; + } + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute) +{ + Track_t *videoTrack = NULL; + Track_t *audioTrack = NULL; + Track_t *current = NULL; + seek_target_flag = 0; + if (!absolute) + { + ffmpeg_printf(10, "seeking %f sec\n", sec); + if (sec == 0) + { + ffmpeg_err("sec = 0 ignoring\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + else + { + int64_t currPts = -1; + int32_t ret = context->playback->Command(context, PLAYBACK_PTS, &currPts); + if (ret != 0) + { + ffmpeg_err("fail to get current PTS\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + sec += currPts / 90000; + } + } + ffmpeg_printf(10, "goto %d sec\n", sec); + if (sec < 0) + { + sec = 0; + } + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); + context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (videoTrack != NULL) + { + current = videoTrack; + } + else if (audioTrack != NULL) + { + current = audioTrack; + } + else + { + ffmpeg_err("no track available to seek\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + if (sec < 0) + { + seek_target_flag |= AVSEEK_FLAG_BACKWARD; + } + getMutex(__FILE__, __FUNCTION__, __LINE__); + if (!context->playback || !context->playback->isPlaying) + { + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_NO_ERROR; + } + ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags); +#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING + if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) + { + /* konfetti: for ts streams seeking frame per seconds does not work (why?). + * I take this algo partly from ffplay.c. + * + * seeking per HTTP does still not work very good. forward seeks everytime + * about 10 seconds, backward does not work. + */ + off_t pos = avio_tell(avContextTab[0]->pb); + ffmpeg_printf(10, "pos %lld %d\n", pos, avContextTab[0]->bit_rate); + if (avContextTab[0]->bit_rate) + { + sec *= avContextTab[0]->bit_rate / 8; + ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate); + } + else + { + sec *= 180000; + } + pos = sec; + if (pos < 0) + { + pos = 0; + } + ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %d\n", pos, sec); + seek_target_bytes = pos; + do_seek_target_bytes = 1; + } + else +#endif + { + seek_target_seconds = sec * AV_TIME_BASE; + do_seek_target_seconds = 1; + } + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length) +{ + ffmpeg_printf(50, "\n"); + Track_t *videoTrack = NULL; + Track_t *audioTrack = NULL; + Track_t *current = NULL; + if (length == NULL) + { + ffmpeg_err("null pointer passed\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); + context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (videoTrack != NULL) + { + current = videoTrack; + } + else if (audioTrack != NULL) + { + current = audioTrack; + } + *length = 0; + if (current != NULL) + { + if (current->duration == 0) + { + return cERR_CONTAINER_FFMPEG_ERR; + } + else + { + *length = current->duration / 1000; + } + } + else + { + if (avContextTab[0] != NULL) + { + *length = avContextTab[0]->duration / 1000; + } + else + { + ffmpeg_err("no Track not context ->no problem :D\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + } + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg) +{ + ffmpeg_printf(10, "track %d\n", *arg); + /* Hellmaster1024: nothing to do here!*/ + int64_t sec = -5; + context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t container_ffmpeg_switch_subtitle(Context_t *context, int32_t *arg) +{ + ffmpeg_printf(10, "track %d\n", *arg); + /* This is made to flush inside the buffer because + * subtitles frame was already read and ignored + * we seek to force ffmpeg to read once again the same data + * but now we will not ignore subtitle frame + */ + int64_t sec = -5; + context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec); + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +/* konfetti comment: I dont like the mechanism of overwriting + * the pointer in infostring. This lead in most cases to + * user errors, like it is in the current version (libeplayer2 <-->e2->servicemp3.cpp) + * From e2 there is passed a tag=strdup here and we overwrite this + * strdupped tag. This lead to dangling pointers which are never freed! + * I do not free the string here because this is the wrong way. The mechanism + * should be changed, or e2 should pass it in a different way... + */ +static int32_t container_ffmpeg_get_info(Context_t *context, char **infoString) +{ + Track_t *videoTrack = NULL; + Track_t *audioTrack = NULL; + char *meta = NULL; + ffmpeg_printf(20, ">\n"); + if (avContextTab[0] != NULL) + { + if ((infoString == NULL) || (*infoString == NULL)) + { + ffmpeg_err("infostring NULL\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + ffmpeg_printf(20, "%s\n", *infoString); + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); + context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if ((meta = searchMeta(avContextTab[0]->metadata, *infoString)) == NULL) + { + if (audioTrack != NULL) + { + AVStream *stream = audioTrack->stream; + meta = searchMeta(stream->metadata, *infoString); + } + if ((meta == NULL) && (videoTrack != NULL)) + { + AVStream *stream = videoTrack->stream; + meta = searchMeta(stream->metadata, *infoString); + } + } + if (meta != NULL) + { + *infoString = strdup(meta); + } + else + { + ffmpeg_printf(1, "no metadata found for \"%s\"\n", *infoString); + *infoString = strdup("not found"); + } + } + else + { + ffmpeg_err("avContext NULL\n"); + return cERR_CONTAINER_FFMPEG_ERR; + } + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int32_t Command(void *_context, ContainerCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_CONTAINER_FFMPEG_NO_ERROR; + ffmpeg_printf(50, "Command %d\n", command); + if (command != CONTAINER_SET_BUFFER_SEEK_TIME && + command != CONTAINER_SET_BUFFER_SIZE && + command != CONTAINER_GET_BUFFER_SIZE && + command != CONTAINER_GET_BUFFER_STATUS && + command != CONTAINER_STOP_BUFFER && + command != CONTAINER_INIT && !avContextTab[0]) + { + return cERR_CONTAINER_FFMPEG_ERR; + } + switch (command) + { + case CONTAINER_INIT: + { + PlayFiles_t *playFilesNames = (PlayFiles_t *)argument; + ret = container_ffmpeg_init(context, playFilesNames); + break; + } + case CONTAINER_PLAY: + { + ret = container_ffmpeg_play(context); + break; + } + case CONTAINER_STOP: + { + ret = container_ffmpeg_stop(context); + break; + } + case CONTAINER_SEEK: + { + ret = container_ffmpeg_seek(context, (int64_t) * ((int64_t *)argument), 0); + break; + } + case CONTAINER_SEEK_ABS: + { + ret = container_ffmpeg_seek(context, (int64_t) * ((int64_t *)argument), -1); + break; + } + case CONTAINER_LENGTH: + { + int64_t length = 0; + ret = container_ffmpeg_get_length(context, &length); + *((int64_t *)argument) = (int64_t)length; + break; + } + case CONTAINER_SWITCH_AUDIO: + { + ret = container_ffmpeg_switch_audio(context, (int32_t *) argument); + break; + } + case CONTAINER_SWITCH_SUBTITLE: + { + ret = container_ffmpeg_switch_subtitle(context, (int32_t *) argument); + break; + } + case CONTAINER_INFO: + { + ret = container_ffmpeg_get_info(context, (char **)argument); + break; + } + case CONTAINER_STATUS: + { + *((int32_t *)argument) = hasPlayThreadStarted; + break; + } + case CONTAINER_LAST_PTS: + { + *((int64_t *)argument) = latestPts; + break; + } + case CONTAINER_SET_BUFFER_SIZE: + { + ret = container_set_ffmpeg_buf_size((int32_t *) argument); + break; + } + case CONTAINER_GET_BUFFER_SIZE: + { + int32_t size = 0; + ret = container_get_ffmpeg_buf_size(&size); + *((int32_t *)argument) = size; + break; + } + default: + ffmpeg_err("ContainerCmd %d not supported!\n", command); + ret = cERR_CONTAINER_FFMPEG_ERR; + break; + } + ffmpeg_printf(50, "exiting with value %d\n", ret); + return ret; +} + +static char *FFMPEG_Capabilities[] = {"aac", "avi", "mkv", "mp4", "ts", "mov", "flv", "flac", "mp3", "mpg", "m2ts", "vob", "evo", "wmv", "wma", "asf", "mp2", "m4v", "m4a", "fla", "divx", "dat", "mpeg", "trp", "mts", "vdr", "ogg", "wav", "wtv", "asx", "mvi", "png", "jpg", "ra", "ram", "rm", "3gp", "amr", "webm", "m3u8", "mpd", NULL }; + +Container_t FFMPEGContainer = +{ + "FFMPEG", + &Command, + FFMPEG_Capabilities +}; \ No newline at end of file diff --git a/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c new file mode 100644 index 0000000..6fdb059 --- /dev/null +++ b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c @@ -0,0 +1,85 @@ +// +// more info +// http://forum.doom9.org/archive/index.php/t-157998.html +// + +#include "flv2mpeg4/flv2mpeg4.h" + + +typedef struct +{ + flv2mpeg4_CTX *ctx; + uint8_t *extradata; + int extradatasize; + + Context_t *out_ctx; + Track_t *track; +} Flv2Mpeg4Context; + + +static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int pts, const uint8_t *buf, int size) +{ + Flv2Mpeg4Context *ctx = usr_data; + if (!ctx) + { + return -1; + } + AudioVideoOut_t avOut; + avOut.data = (char *)buf; + avOut.len = size; + avOut.pts = ctx->track->pts; + avOut.dts = ctx->track->dts; + avOut.extradata = ctx->extradata; + avOut.extralen = ctx->extradatasize; + avOut.frameRate = ctx->track->frame_rate; + avOut.timeScale = ctx->track->TimeScale; + avOut.width = ctx->track->width; + avOut.height = ctx->track->height; + avOut.type = "video"; + if (ctx->out_ctx->output->video->Write(ctx->out_ctx, &avOut) < 0) + { + ffmpeg_err("writing data to video device failed\n"); + } + return 0; +} + +static int flv2mpeg4_context_write_extradata_cb(void *usr_data, int width, int height, int bitrate, const uint8_t *extradata, int extradatasize) +{ + Flv2Mpeg4Context *ctx = usr_data; + if (!ctx) + { + return -1; + } + free(ctx->extradata); + ctx->extradata = malloc(extradatasize); + memcpy(ctx->extradata, extradata, extradatasize); + ctx->extradatasize = extradatasize; + return 0; +} + +static void flv2mpeg4_context_reset(Flv2Mpeg4Context *context) +{ + if (context == NULL || context->ctx == NULL) + return; + flv2mpeg4_set_frame(context->ctx, 0, 0); +} + +static int flv2mpeg4_write_packet(Context_t *out_ctx, Flv2Mpeg4Context *mpeg4p2_ctx, Track_t *track, int cAVIdx, int64_t *pts_current, int64_t *pts_latest, AVPacket *pkt) +{ + if (!mpeg4p2_ctx->ctx) + { + mpeg4p2_ctx->ctx = flv2mpeg4_init_ctx(mpeg4p2_ctx, track->width, track->height, flv2mpeg4_context_write_packet_cb, flv2mpeg4_context_write_extradata_cb); + flv2mpeg4_prepare_extra_data(mpeg4p2_ctx->ctx); + } + *pts_current = track->pts = calcPts(cAVIdx, track->stream, pkt->pts); + if ((*pts_current > *pts_latest) && (*pts_current != INVALID_PTS_VALUE)) + { + *pts_latest = *pts_current; + } + track->dts = calcPts(cAVIdx, track->stream, pkt->dts); + mpeg4p2_ctx->out_ctx = out_ctx; + mpeg4p2_ctx->track = track; + uint32_t time_ms = (uint32_t)(track->pts / 90); + return flv2mpeg4_process_flv_packet(mpeg4p2_ctx->ctx, 0, pkt->data, pkt->size, time_ms); +} + diff --git a/libeplayer3-arm/container/mpeg4p2_ffmpeg.c b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c new file mode 100644 index 0000000..288fe86 --- /dev/null +++ b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c @@ -0,0 +1,210 @@ +// +// mpeg4-part2 in mipsel receivers +// http://forums.openpli.org/topic/39326-gstreamer10-and-mpeg4-part2/?hl=%2Bmpeg4+%2Bpart2 +// + +#define MPEG4P2_MAX_B_FRAMES_COUNT 5 + +typedef struct +{ + int b_frames_count; + int first_ip_frame_written; + int64_t packet_duration; + AVPacket *b_frames[MPEG4P2_MAX_B_FRAMES_COUNT]; + AVPacket *second_ip_frame; +} Mpeg4P2Context; + + +static void set_packet(AVPacket **pkt_dest, AVPacket *pkt_src) +{ + if (pkt_dest == NULL) + return; + if (*pkt_dest != NULL) + { + wrapped_packet_unref(*pkt_dest); + av_free(*pkt_dest); + } + *pkt_dest = av_malloc(sizeof(AVPacket)); + av_copy_packet(*pkt_dest, pkt_src); +} + +static int filter_packet(AVBitStreamFilterContext *bsf_ctx, AVCodecContext *enc_ctx, AVPacket *pkt) +{ + int ret; + AVPacket new_pkt = *pkt; + ret = av_bitstream_filter_filter(bsf_ctx, enc_ctx, NULL, + &new_pkt.data, &new_pkt.size, + pkt->data, pkt->size, + pkt->flags & AV_PKT_FLAG_KEY); + if (ret == 0 && new_pkt.data != pkt->data) + { + if ((ret = av_copy_packet(&new_pkt, pkt)) < 0) + return -1; + ret = 1; + } + if (ret > 0) + { + pkt->side_data = NULL; + pkt->side_data_elems = 0; + wrapped_packet_unref(pkt); + new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, + av_buffer_default_free, NULL, 0); + if (!new_pkt.buf) + return -1; + } + if (ret < 0) + { + ffmpeg_err("Failed to filter bitstream with filter %s for stream %d with codec %s\n", + bsf_ctx->filter->name, pkt->stream_index, + avcodec_get_name(enc_ctx->codec_id)); + return -1; + } + *pkt = new_pkt; + return 0; +} + +static void mpeg4p2_context_reset(Mpeg4P2Context *context) +{ + if (context == NULL) + return; + int i; + for (i = 0; i < MPEG4P2_MAX_B_FRAMES_COUNT; i++) + { + if (context->b_frames[i] != NULL) + { + wrapped_packet_unref(context->b_frames[i]); + av_free(context->b_frames[i]); + } + context->b_frames[i] = NULL; + } + if (context->second_ip_frame != NULL) + { + wrapped_packet_unref(context->second_ip_frame); + av_free(context->second_ip_frame); + } + context->second_ip_frame = NULL; + context->b_frames_count = 0; + context->first_ip_frame_written = 0; + context->packet_duration = 0; +} + +static void mpeg4p2_write(Context_t *ctx, Track_t *track, int avContextIdx, int64_t *currentVideoPts, int64_t *latestPts, AVPacket *pkt) +{ + *currentVideoPts = track->pts = calcPts(avContextIdx, track->stream, pkt->pts); + if ((*currentVideoPts > *latestPts) && (*currentVideoPts != INVALID_PTS_VALUE)) + { + *latestPts = *currentVideoPts; + } + track->dts = calcPts(avContextIdx, track->stream, pkt->dts); + AudioVideoOut_t avOut; + avOut.data = pkt->data; + avOut.len = pkt->size; + avOut.pts = track->pts; + avOut.dts = track->dts; + avOut.extradata = track->extraData; + avOut.extralen = track->extraSize; + avOut.frameRate = track->frame_rate; + avOut.timeScale = track->TimeScale; + avOut.width = track->width; + avOut.height = track->height; + avOut.type = "video"; + if (ctx->output->video->Write(ctx, &avOut) < 0) + { + ffmpeg_err("writing data to video device failed\n"); + } +} + +static int mpeg4p2_write_packet(Context_t *ctx, Mpeg4P2Context *mpeg4p2_ctx, Track_t *track, int cAVIdx, int64_t *pts_current, int64_t *pts_latest, AVPacket *pkt) +{ + uint8_t *data = pkt->data; + int data_len = pkt->size; + int pos = 0; + if (mpeg4p2_ctx->packet_duration == 0) + { + mpeg4p2_ctx->packet_duration = pkt->duration; + } + while (pos < data_len) + { + if (memcmp(&data[pos], "\x00\x00\x01\xb6", 4)) + { + pos++; + continue; + } + pos += 4; + switch ((data[pos] & 0xC0) >> 6) + { + case 0: // I-Frame + case 1: // P-Frame + if (!mpeg4p2_ctx->first_ip_frame_written) + { + mpeg4p2_ctx->first_ip_frame_written = 1; + pkt->pts = pkt->dts + mpeg4p2_ctx->packet_duration; + ffmpeg_printf(100, "Writing first I/P packet\n"); + mpeg4p2_write(ctx, track, cAVIdx, pts_current, pts_latest, pkt); + return 0; + } + else if (!mpeg4p2_ctx->second_ip_frame) + { + set_packet(&mpeg4p2_ctx->second_ip_frame, pkt); + return 0; + } + else + { + if (!mpeg4p2_ctx->b_frames_count) + { + mpeg4p2_ctx->second_ip_frame->pts = mpeg4p2_ctx->second_ip_frame->dts + mpeg4p2_ctx->packet_duration; + ffmpeg_printf(100, "Writing second I/P packet(1)\n"); + mpeg4p2_write(ctx, track, cAVIdx, pts_current, pts_latest, mpeg4p2_ctx->second_ip_frame); + set_packet(&mpeg4p2_ctx->second_ip_frame, pkt); + return 0; + } + else + { + mpeg4p2_ctx->second_ip_frame->pts = mpeg4p2_ctx->b_frames[mpeg4p2_ctx->b_frames_count - 1]->dts + mpeg4p2_ctx->packet_duration; + mpeg4p2_ctx->b_frames[0]->pts = mpeg4p2_ctx->second_ip_frame->dts + mpeg4p2_ctx->packet_duration; + int i; + for (i = 1; i < mpeg4p2_ctx->b_frames_count; i++) + { + mpeg4p2_ctx->b_frames[i]->pts = mpeg4p2_ctx->b_frames[i - 1]->dts + mpeg4p2_ctx->packet_duration; + } + ffmpeg_printf(100, "Writing second I/P packet(2)\n"); + mpeg4p2_write(ctx, track, cAVIdx, pts_current, pts_latest, mpeg4p2_ctx->second_ip_frame); + set_packet(&mpeg4p2_ctx->second_ip_frame, pkt); + for (i = 0; i < mpeg4p2_ctx->b_frames_count; i++) + { + ffmpeg_printf(100, "Writing B-frame[%d]\n", i); + mpeg4p2_write(ctx, track, cAVIdx, pts_current, pts_latest, mpeg4p2_ctx->b_frames[i]); + } + mpeg4p2_ctx->b_frames_count = 0; + return 0; + } + } + break; + case 3: // S-Frame + break; + case 2: // B-Frame + if (!mpeg4p2_ctx->second_ip_frame) + { + ffmpeg_err("Cannot predict B-Frame without surrounding I/P-Frames, dropping..."); + return 0; + } + if (mpeg4p2_ctx->b_frames_count == MPEG4P2_MAX_B_FRAMES_COUNT) + { + ffmpeg_err("Oops max B-Frames count = %d, reached", MPEG4P2_MAX_B_FRAMES_COUNT); + // not recoverable, to fix just increase MPEG4P2_MAX_B_FRAMES_COUNT + return -1; + } + else + { + ffmpeg_printf(100, "Storing B-Frame\n"); + set_packet(&mpeg4p2_ctx->b_frames[mpeg4p2_ctx->b_frames_count++], pkt); + return 0; + } + case 4: + default: + break; + } + } + return 0; +} + diff --git a/libeplayer3-arm/container/wrapped_ffmpeg.c b/libeplayer3-arm/container/wrapped_ffmpeg.c new file mode 100644 index 0000000..589311a --- /dev/null +++ b/libeplayer3-arm/container/wrapped_ffmpeg.c @@ -0,0 +1,184 @@ +/* + * Wrapper functions for FFMPEG API which + * allows to compile and use exteplayer3 + * with old ffmpeg libs + */ +static void wrapped_frame_free(void *param) +{ +#if (LIBAVCODEC_VERSION_MAJOR >= 55) + av_frame_free(param); +#else + avcodec_free_frame(param); +#endif +} + +static void *wrapped_frame_alloc() +{ +#if (LIBAVCODEC_VERSION_MAJOR >= 55) + return av_frame_alloc(); +#else + return avcodec_alloc_frame(); +#endif +} + +static void wrapped_frame_unref(void *param) +{ +#if (LIBAVCODEC_VERSION_MAJOR >= 55) + av_frame_unref(param); +#else + avcodec_get_frame_defaults(param); +#endif +} + +static void wrapped_packet_unref(void *param) +{ +#if (LIBAVCODEC_VERSION_MAJOR > 55) + av_packet_unref(param); +#else + av_free_packet(param); +#endif +} + +static void wrapped_set_max_analyze_duration(void *param, int val) +{ +#if (LIBAVFORMAT_VERSION_MAJOR > 55) && (LIBAVFORMAT_VERSION_MAJOR < 56) + ((AVFormatContext *)param)->max_analyze_duration2 = val; +#else + ((AVFormatContext *)param)->max_analyze_duration = 1; +#endif +} + +static int64_t get_packet_duration(AVPacket *packet) +{ +#if LIBAVFORMAT_VERSION_MAJOR > 56 + return packet->duration; +#else + return packet->convergence_duration; +#endif +} + +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) +static AVCodecParameters *get_codecpar(AVStream *stream) +{ + return stream->codecpar; +} +#else +static AVCodecContext *get_codecpar(AVStream *stream) +{ + return stream->codec; +} +#endif + +static AVRational get_frame_rate(AVStream *stream) +{ + AVRational rateRational = stream->avg_frame_rate; + if (0 == rateRational.den) + { + rateRational = stream->r_frame_rate; + } + return rateRational; +} + +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) +typedef struct CodecCtxStoreItem_s +{ + uint32_t cAVIdx; + int id; + AVCodecContext *avCodecCtx; + void *next; +} CodecCtxStoreItem_t; + +static CodecCtxStoreItem_t *g_codecCtxStoreListHead = NULL; + +AVCodecContext *restore_avcodec_context(uint32_t cAVIdx, int32_t id) +{ + CodecCtxStoreItem_t *ptr = g_codecCtxStoreListHead; + while (ptr != NULL) + { + if (ptr->cAVIdx == cAVIdx && ptr->id == id) + { + return ptr->avCodecCtx; + } + ptr = ptr->next; + } + return NULL; +} + +void free_all_stored_avcodec_context() +{ + while (g_codecCtxStoreListHead != NULL) + { + CodecCtxStoreItem_t *ptr = g_codecCtxStoreListHead->next; + free(g_codecCtxStoreListHead); + g_codecCtxStoreListHead = ptr; + } +} + +int store_avcodec_context(AVCodecContext *avCodecCtx, uint32_t cAVIdx, int id) +{ + CodecCtxStoreItem_t *ptr = malloc(sizeof(CodecCtxStoreItem_t)); + if (!ptr) + { + return -1; + } + memset(ptr, 0x00, sizeof(CodecCtxStoreItem_t)); + ptr->next = g_codecCtxStoreListHead; + g_codecCtxStoreListHead = ptr; + return 0; +} +#else +void free_all_stored_avcodec_context() +{ +} +#endif + +static AVCodecContext *wrapped_avcodec_get_context(uint32_t cAVIdx, AVStream *stream) +{ +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) + AVCodecContext *avCodecCtx = restore_avcodec_context(cAVIdx, stream->id); + if (!avCodecCtx) + { + avCodecCtx = avcodec_alloc_context3(NULL); + if (!avCodecCtx) + { + fprintf(stderr, "context3 alloc for stream %d failed\n", (int)stream->id); + return NULL; + } + if (avcodec_parameters_to_context(avCodecCtx, stream->codecpar) < 0) + { + fprintf(stderr, "parameters to context for stream %d failed\n", (int)stream->id); + avcodec_free_context(&avCodecCtx); + return NULL; + } + av_codec_set_pkt_timebase(avCodecCtx, stream->time_base); + store_avcodec_context(avCodecCtx, cAVIdx, stream->id); + return avCodecCtx; + } +#else + return stream->codec; +#endif +} + +static void wrapped_avcodec_flush_buffers(uint32_t cAVIdx) +{ +#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) + CodecCtxStoreItem_t *ptr = g_codecCtxStoreListHead; + while (ptr != NULL) + { + if (ptr->cAVIdx == cAVIdx && ptr->avCodecCtx && ptr->avCodecCtx->codec) + { + avcodec_flush_buffers(ptr->avCodecCtx); + } + ptr = ptr->next; + } +#else + uint32_t j; + for (j = 0; j < avContextTab[cAVIdx]->nb_streams; j++) + { + if (avContextTab[cAVIdx]->streams[j]->codec && avContextTab[cAVIdx]->streams[j]->codec->codec) + { + avcodec_flush_buffers(avContextTab[cAVIdx]->streams[j]->codec); + } + } +#endif +} diff --git a/libeplayer3-arm/external/ffmpeg/get_bits.h b/libeplayer3-arm/external/ffmpeg/get_bits.h new file mode 100644 index 0000000..658253f --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/get_bits.h @@ -0,0 +1,544 @@ +/* + * copyright (c) 2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * bitstream reader API header. + */ + +#ifndef AVCODEC_GET_BITS_H +#define AVCODEC_GET_BITS_H + +#include +#include +#include +#include +#include +#include + +#include "mathops.h" + +typedef struct GetBitContext +{ + const uint8_t *buffer, *buffer_end; + int index; + int size_in_bits; + int size_in_bits_plus8; +} GetBitContext; + +/* Bitstream reader API docs: + * name + * arbitrary name which is used as prefix for the internal variables + * + * gb + * getbitcontext + * + * OPEN_READER(name, gb) + * load gb into local variables + * + * CLOSE_READER(name, gb) + * store local vars in gb + * + * UPDATE_CACHE(name, gb) + * Refill the internal cache from the bitstream. + * After this call at least MIN_CACHE_BITS will be available. + * + * GET_CACHE(name, gb) + * Will output the contents of the internal cache, + * next bit is MSB of 32 or 64 bits (FIXME 64 bits). + * + * SHOW_UBITS(name, gb, num) + * Will return the next num bits. + * + * SHOW_SBITS(name, gb, num) + * Will return the next num bits and do sign extension. + * + * SKIP_BITS(name, gb, num) + * Will skip over the next num bits. + * Note, this is equivalent to SKIP_CACHE; SKIP_COUNTER. + * + * SKIP_CACHE(name, gb, num) + * Will remove the next num bits from the cache (note SKIP_COUNTER + * MUST be called before UPDATE_CACHE / CLOSE_READER). + * + * SKIP_COUNTER(name, gb, num) + * Will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS). + * + * LAST_SKIP_BITS(name, gb, num) + * Like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER. + * + * BITS_LEFT(name, gb) + * Return the number of bits left + * + * For examples see get_bits, show_bits, skip_bits, get_vlc. + */ + +#ifdef LONG_BITSTREAM_READER +# define MIN_CACHE_BITS 32 +#else +# define MIN_CACHE_BITS 25 +#endif + +#define OPEN_READER_NOSIZE(name, gb) \ + unsigned int name ## _index = (gb)->index; \ + unsigned int av_unused name ## _cache + + +#define OPEN_READER(name, gb) OPEN_READER_NOSIZE(name, gb) +#define BITS_AVAILABLE(name, gb) 1 + + +#define CLOSE_READER(name, gb) (gb)->index = name ## _index + +# ifdef LONG_BITSTREAM_READER + +# define UPDATE_CACHE_LE(name, gb) name ## _cache = \ + AV_RL64((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) + +# define UPDATE_CACHE_BE(name, gb) name ## _cache = \ + AV_RB64((gb)->buffer + (name ## _index >> 3)) >> (32 - (name ## _index & 7)) + +#else + +# define UPDATE_CACHE_LE(name, gb) name ## _cache = \ + AV_RL32((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) + +# define UPDATE_CACHE_BE(name, gb) name ## _cache = \ + AV_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7) + +#endif + + +#ifdef BITSTREAM_READER_LE + +# define UPDATE_CACHE(name, gb) UPDATE_CACHE_LE(name, gb) + +# define SKIP_CACHE(name, gb, num) name ## _cache >>= (num) + +#else + +# define UPDATE_CACHE(name, gb) UPDATE_CACHE_BE(name, gb) + +# define SKIP_CACHE(name, gb, num) name ## _cache <<= (num) + +#endif + +#define SKIP_COUNTER(name, gb, num) name ## _index += (num) + + +#define BITS_LEFT(name, gb) ((int)((gb)->size_in_bits - name ## _index)) + +#define SKIP_BITS(name, gb, num) \ + do { \ + SKIP_CACHE(name, gb, num); \ + SKIP_COUNTER(name, gb, num); \ + } while (0) + +#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) + +#define SHOW_UBITS_LE(name, gb, num) zero_extend(name ## _cache, num) +#define SHOW_SBITS_LE(name, gb, num) sign_extend(name ## _cache, num) + +#define SHOW_UBITS_BE(name, gb, num) NEG_USR32(name ## _cache, num) +#define SHOW_SBITS_BE(name, gb, num) NEG_SSR32(name ## _cache, num) + +#ifdef BITSTREAM_READER_LE +# define SHOW_UBITS(name, gb, num) SHOW_UBITS_LE(name, gb, num) +# define SHOW_SBITS(name, gb, num) SHOW_SBITS_LE(name, gb, num) +#else +# define SHOW_UBITS(name, gb, num) SHOW_UBITS_BE(name, gb, num) +# define SHOW_SBITS(name, gb, num) SHOW_SBITS_BE(name, gb, num) +#endif + +#define GET_CACHE(name, gb) ((uint32_t) name ## _cache) + +static inline int get_bits_count(const GetBitContext *s) +{ + return s->index; +} + +static inline void skip_bits_long(GetBitContext *s, int n) +{ + s->index += n; +} + +/** + * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). + * if MSB not set it is negative + * @param n length in bits + */ +static inline int get_xbits(GetBitContext *s, int n) +{ + register int sign; + register int32_t cache; + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + cache = GET_CACHE(re, s); + sign = ~cache >> 31; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; +} + +static inline int get_xbits_le(GetBitContext *s, int n) +{ + register int sign; + register int32_t cache; + OPEN_READER(re, s); + UPDATE_CACHE_LE(re, s); + cache = GET_CACHE(re, s); + sign = sign_extend(~cache, n) >> 31; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return (zero_extend(sign ^ cache, n) ^ sign) - sign; +} + +static inline int get_sbits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_SBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return tmp; +} + +/** + * Read 1-25 bits. + */ +static inline unsigned int get_bits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return tmp; +} + +/** + * Read 0-25 bits. + */ +static inline int get_bitsz(GetBitContext *s, int n) +{ + return n ? get_bits(s, n) : 0; +} + +static inline unsigned int get_bits_le(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + UPDATE_CACHE_LE(re, s); + tmp = SHOW_UBITS_LE(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return tmp; +} + +/** + * Show 1-25 bits. + */ +static inline unsigned int show_bits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER_NOSIZE(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + return tmp; +} + +static inline void skip_bits(GetBitContext *s, int n) +{ + OPEN_READER(re, s); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); +} + +static inline unsigned int get_bits1(GetBitContext *s) +{ + unsigned int index = s->index; + uint8_t result = s->buffer[index >> 3]; +#ifdef BITSTREAM_READER_LE + result >>= index & 7; + result &= 1; +#else + result <<= index & 7; + result >>= 8 - 1; +#endif + index++; + s->index = index; + return result; +} + +static inline unsigned int show_bits1(GetBitContext *s) +{ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s) +{ + skip_bits(s, 1); +} + +/** + * Read 0-32 bits. + */ +static inline unsigned int get_bits_long(GetBitContext *s, int n) +{ + if (!n) + { + return 0; + } + else if (n <= MIN_CACHE_BITS) + { + return get_bits(s, n); + } + else + { +#ifdef BITSTREAM_READER_LE + unsigned ret = get_bits(s, 16); + return ret | (get_bits(s, n - 16) << 16); +#else + unsigned ret = get_bits(s, 16) << (n - 16); + return ret | get_bits(s, n - 16); +#endif + } +} + +/** + * Read 0-64 bits. + */ +static inline uint64_t get_bits64(GetBitContext *s, int n) +{ + if (n <= 32) + { + return get_bits_long(s, n); + } + else + { +#ifdef BITSTREAM_READER_LE + uint64_t ret = get_bits_long(s, 32); + return ret | (uint64_t) get_bits_long(s, n - 32) << 32; +#else + uint64_t ret = (uint64_t) get_bits_long(s, n - 32) << 32; + return ret | get_bits_long(s, 32); +#endif + } +} + +/** + * Read 0-32 bits as a signed integer. + */ +static inline int get_sbits_long(GetBitContext *s, int n) +{ + /* sign_extend(x, 0) is undefined */ + if (!n) + return 0; + return sign_extend(get_bits_long(s, n), n); +} + +/** + * Show 0-32 bits. + */ +static inline unsigned int show_bits_long(GetBitContext *s, int n) +{ + if (n <= MIN_CACHE_BITS) + { + return show_bits(s, n); + } + else + { + GetBitContext gb = *s; + return get_bits_long(&gb, n); + } +} + +static inline int check_marker(void *logctx, GetBitContext *s, const char *msg) +{ + int bit = get_bits1(s); + return bit; +} + +/** + * Initialize GetBitContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, + int bit_size) +{ + int buffer_size; + int ret = 0; + if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) + { + bit_size = 0; + buffer = NULL; + ret = AVERROR_INVALIDDATA; + } + buffer_size = (bit_size + 7) >> 3; + s->buffer = buffer; + s->size_in_bits = bit_size; + s->size_in_bits_plus8 = bit_size + 8; + s->buffer_end = buffer + buffer_size; + s->index = 0; + return ret; +} + +/** + * Initialize GetBitContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int init_get_bits8(GetBitContext *s, const uint8_t *buffer, + int byte_size) +{ + if (byte_size > INT_MAX / 8 || byte_size < 0) + byte_size = -1; + return init_get_bits(s, buffer, byte_size * 8); +} + +static inline const uint8_t *align_get_bits(GetBitContext *s) +{ + int n = -get_bits_count(s) & 7; + if (n) + skip_bits(s, n); + return s->buffer + (s->index >> 3); +} + +/** + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +#define GET_VLC(code, name, gb, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + unsigned int index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + code = table[index][0]; \ + n = table[index][1]; \ + \ + if (max_depth > 1 && n < 0) { \ + LAST_SKIP_BITS(name, gb, bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + } \ + } \ + SKIP_BITS(name, gb, n); \ + } while (0) + +#define GET_RL_VLC(level, run, name, gb, table, bits, \ + max_depth, need_update) \ +do { \ + int n, nb_bits; \ + unsigned int index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + SKIP_BITS(name, gb, bits); \ + if (need_update) { \ + UPDATE_CACHE(name, gb); \ + } \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + if (need_update) { \ + UPDATE_CACHE(name, gb); \ + } \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + SKIP_BITS(name, gb, n); \ +} while (0) + + +static inline int decode012(GetBitContext *gb) +{ + int n; + n = get_bits1(gb); + if (n == 0) + return 0; + else + return get_bits1(gb) + 1; +} + +static inline int decode210(GetBitContext *gb) +{ + if (get_bits1(gb)) + return 0; + else + return 2 - get_bits1(gb); +} + +static inline int get_bits_left(GetBitContext *gb) +{ + return gb->size_in_bits - get_bits_count(gb); +} + +static inline int skip_1stop_8data_bits(GetBitContext *gb) +{ + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + while (get_bits1(gb)) + { + skip_bits(gb, 8); + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; + } + return 0; +} + +#endif /* AVCODEC_GET_BITS_H */ \ No newline at end of file diff --git a/libeplayer3-arm/external/ffmpeg/latmenc.h b/libeplayer3-arm/external/ffmpeg/latmenc.h new file mode 100644 index 0000000..e5d3345 --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/latmenc.h @@ -0,0 +1,45 @@ +/* + * LATM/LOAS muxer + * Copyright (c) 2011 Kieran Kunhya + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LATMENC_H +#define AVCODEC_LATMENC_H + +#include + +#define MAX_EXTRADATA_SIZE 1024 + +typedef struct LATMContext +{ + int off; + int channel_conf; + int object_type; + int counter; + int mod; // default 0x0014 + uint8_t loas_header[3]; + uint8_t buffer[0x1fff + MAX_EXTRADATA_SIZE + 1024]; + int len; +} LATMContext; + +int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size); +int latmenc_write_packet(LATMContext *ctx, uint8_t *data, int size, uint8_t *extradata, int extradata_size); + +#endif /* AVCODEC_LATMENC_H */ + diff --git a/libeplayer3-arm/external/ffmpeg/mathops.h b/libeplayer3-arm/external/ffmpeg/mathops.h new file mode 100644 index 0000000..641324e --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/mathops.h @@ -0,0 +1,56 @@ +/* + * simple math operations + * Copyright (c) 2001, 2002 Fabrice Bellard + * Copyright (c) 2006 Michael Niedermayer et al + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVCODEC_MATHOPS_H +#define AVCODEC_MATHOPS_H + +#include +#include + +#ifndef NEG_USR32 +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +#ifndef NEG_SSR32 +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +#endif + +#ifndef sign_extend +static inline av_const int sign_extend(int val, unsigned bits) +{ + unsigned shift = 8 * sizeof(int) - bits; + union + { + unsigned u; + int s; + } v = { (unsigned) val << shift }; + return v.s >> shift; +} +#endif + +#ifndef zero_extend +static inline av_const unsigned zero_extend(unsigned val, unsigned bits) +{ + return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits); +} +#endif + +#endif /* AVCODEC_MATHOPS_H */ diff --git a/libeplayer3-arm/external/ffmpeg/mpeg4audio.h b/libeplayer3-arm/external/ffmpeg/mpeg4audio.h new file mode 100644 index 0000000..940dff8 --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/mpeg4audio.h @@ -0,0 +1,112 @@ +/* + * MPEG-4 Audio common header + * Copyright (c) 2008 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEG4AUDIO_H +#define AVCODEC_MPEG4AUDIO_H + +#include +#include "get_bits.h" +#include "put_bits.h" + +typedef struct MPEG4AudioConfig +{ + int object_type; + int sampling_index; + int sample_rate; + int chan_config; + int sbr; ///< -1 implicit, 1 presence + int ext_object_type; + int ext_sampling_index; + int ext_sample_rate; + int ext_chan_config; + int channels; + int ps; ///< -1 implicit, 1 presence + int frame_length_short; +} MPEG4AudioConfig; + +extern const int avpriv_mpeg4audio_sample_rates[16]; +extern const uint8_t ff_mpeg4audio_channels[8]; + +/** + * Parse MPEG-4 systems extradata to retrieve audio configuration. + * @param[in] c MPEG4AudioConfig structure to fill. + * @param[in] buf Extradata from container. + * @param[in] bit_size Extradata size in bits. + * @param[in] sync_extension look for a sync extension after config if true. + * @return On error -1 is returned, on success AudioSpecificConfig bit index in extradata. + */ +int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, + int bit_size, int sync_extension); + +enum AudioObjectType +{ + AOT_NULL, + // Support? Name + AOT_AAC_MAIN, ///< Y Main + AOT_AAC_LC, ///< Y Low Complexity + AOT_AAC_SSR, ///< N (code in SoC repo) Scalable Sample Rate + AOT_AAC_LTP, ///< Y Long Term Prediction + AOT_SBR, ///< Y Spectral Band Replication + AOT_AAC_SCALABLE, ///< N Scalable + AOT_TWINVQ, ///< N Twin Vector Quantizer + AOT_CELP, ///< N Code Excited Linear Prediction + AOT_HVXC, ///< N Harmonic Vector eXcitation Coding + AOT_TTSI = 12, ///< N Text-To-Speech Interface + AOT_MAINSYNTH, ///< N Main Synthesis + AOT_WAVESYNTH, ///< N Wavetable Synthesis + AOT_MIDI, ///< N General MIDI + AOT_SAFX, ///< N Algorithmic Synthesis and Audio Effects + AOT_ER_AAC_LC, ///< N Error Resilient Low Complexity + AOT_ER_AAC_LTP = 19, ///< N Error Resilient Long Term Prediction + AOT_ER_AAC_SCALABLE, ///< N Error Resilient Scalable + AOT_ER_TWINVQ, ///< N Error Resilient Twin Vector Quantizer + AOT_ER_BSAC, ///< N Error Resilient Bit-Sliced Arithmetic Coding + AOT_ER_AAC_LD, ///< N Error Resilient Low Delay + AOT_ER_CELP, ///< N Error Resilient Code Excited Linear Prediction + AOT_ER_HVXC, ///< N Error Resilient Harmonic Vector eXcitation Coding + AOT_ER_HILN, ///< N Error Resilient Harmonic and Individual Lines plus Noise + AOT_ER_PARAM, ///< N Error Resilient Parametric + AOT_SSC, ///< N SinuSoidal Coding + AOT_PS, ///< N Parametric Stereo + AOT_SURROUND, ///< N MPEG Surround + AOT_ESCAPE, ///< Y Escape Value + AOT_L1, ///< Y Layer 1 + AOT_L2, ///< Y Layer 2 + AOT_L3, ///< Y Layer 3 + AOT_DST, ///< N Direct Stream Transfer + AOT_ALS, ///< Y Audio LosslesS + AOT_SLS, ///< N Scalable LosslesS + AOT_SLS_NON_CORE, ///< N Scalable LosslesS (non core) + AOT_ER_AAC_ELD, ///< N Error Resilient Enhanced Low Delay + AOT_SMR_SIMPLE, ///< N Symbolic Music Representation Simple + AOT_SMR_MAIN, ///< N Symbolic Music Representation Main + AOT_USAC_NOSBR, ///< N Unified Speech and Audio Coding (no SBR) + AOT_SAOC, ///< N Spatial Audio Object Coding + AOT_LD_SURROUND, ///< N Low Delay MPEG Surround + AOT_USAC, ///< N Unified Speech and Audio Coding +}; + +#define MAX_PCE_SIZE 320 /// + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * bitstream writer API + */ + +#ifndef AVCODEC_PUT_BITS_H +#define AVCODEC_PUT_BITS_H + +#include +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" + +typedef struct PutBitContext +{ + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; + int size_in_bits; +} PutBitContext; + +/** + * Initialize the PutBitContext s. + * + * @param buffer the buffer where to put bits + * @param buffer_size the size in bytes of buffer + */ +static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, + int buffer_size) +{ + if (buffer_size < 0) + { + buffer_size = 0; + buffer = NULL; + } + s->size_in_bits = 8 * buffer_size; + s->buf = buffer; + s->buf_end = s->buf + buffer_size; + s->buf_ptr = s->buf; + s->bit_left = 32; + s->bit_buf = 0; +} + +/** + * Rebase the bit writer onto a reallocated buffer. + * + * @param buffer the buffer where to put bits + * @param buffer_size the size in bytes of buffer, + * must be larger than the previous size + */ +static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer, + int buffer_size) +{ + av_assert0(8 * buffer_size > s->size_in_bits); + s->buf_end = buffer + buffer_size; + s->buf_ptr = buffer + (s->buf_ptr - s->buf); + s->buf = buffer; + s->size_in_bits = 8 * buffer_size; +} + +/** + * @return the total number of bits written to the bitstream. + */ +static inline int put_bits_count(PutBitContext *s) +{ + return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; +} + +/** + * @return the number of bits available in the bitstream. + */ +static inline int put_bits_left(PutBitContext *s) +{ + return (s->buf_end - s->buf_ptr) * 8 - 32 + s->bit_left; +} + +/** + * Pad the end of the output stream with zeros. + */ +static inline void flush_put_bits(PutBitContext *s) +{ +#ifndef BITSTREAM_WRITER_LE + if (s->bit_left < 32) + s->bit_buf <<= s->bit_left; +#endif + while (s->bit_left < 32) + { + av_assert0(s->buf_ptr < s->buf_end); +#ifdef BITSTREAM_WRITER_LE + *s->buf_ptr++ = s->bit_buf; + s->bit_buf >>= 8; +#else + *s->buf_ptr++ = s->bit_buf >> 24; + s->bit_buf <<= 8; +#endif + s->bit_left += 8; + } + s->bit_left = 32; + s->bit_buf = 0; +} + +#ifdef BITSTREAM_WRITER_LE +#define avpriv_align_put_bits align_put_bits_unsupported_here +#define avpriv_put_string ff_put_string_unsupported_here +#define avpriv_copy_bits avpriv_copy_bits_unsupported_here +#else +/** + * Pad the bitstream with zeros up to the next byte boundary. + */ +void avpriv_align_put_bits(PutBitContext *s); + +/** + * Put the string string in the bitstream. + * + * @param terminate_string 0-terminates the written string if value is 1 + */ +void avpriv_put_string(PutBitContext *pb, const char *string, + int terminate_string); + +/** + * Copy the content of src to the bitstream. + * + * @param length the number of bits of src to copy + */ +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length); +#endif + +/** + * Write up to 31 bits into a bitstream. + * Use put_bits32 to write 32 bits. + */ +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + av_assert2(n <= 31 && value < (1U << n)); + bit_buf = s->bit_buf; + bit_left = s->bit_left; + /* XXX: optimize */ +#ifdef BITSTREAM_WRITER_LE + bit_buf |= value << (32 - bit_left); + if (n >= bit_left) + { + if (3 < s->buf_end - s->buf_ptr) + { + AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } + else + { + av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); + av_assert2(0); + } + bit_buf = value >> bit_left; + bit_left += 32; + } + bit_left -= n; +#else + if (n < bit_left) + { + bit_buf = (bit_buf << n) | value; + bit_left -= n; + } + else + { + bit_buf <<= bit_left; + bit_buf |= value >> (n - bit_left); + if (3 < s->buf_end - s->buf_ptr) + { + AV_WB32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } + else + { + av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); + av_assert2(0); + } + bit_left += 32 - n; + bit_buf = value; + } +#endif + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} + +static inline void put_sbits(PutBitContext *pb, int n, int32_t value) +{ + av_assert2(n >= 0 && n <= 31); + put_bits(pb, n, av_mod_uintp2(value, n)); +} + +/** + * Write exactly 32 bits into a bitstream. + */ +static void av_unused put_bits32(PutBitContext *s, uint32_t value) +{ + int lo = value & 0xffff; + int hi = value >> 16; +#ifdef BITSTREAM_WRITER_LE + put_bits(s, 16, lo); + put_bits(s, 16, hi); +#else + put_bits(s, 16, hi); + put_bits(s, 16, lo); +#endif +} + +/** + * Return the pointer to the byte where the bitstream writer will put + * the next bit. + */ +static inline uint8_t *put_bits_ptr(PutBitContext *s) +{ + return s->buf_ptr; +} + +/** + * Skip the given number of bytes. + * PutBitContext must be flushed & aligned to a byte boundary before calling this. + */ +static inline void skip_put_bytes(PutBitContext *s, int n) +{ + av_assert2((put_bits_count(s) & 7) == 0); + av_assert2(s->bit_left == 32); + av_assert0(n <= s->buf_end - s->buf_ptr); + s->buf_ptr += n; +} + +/** + * Skip the given number of bits. + * Must only be used if the actual values in the bitstream do not matter. + * If n is 0 the behavior is undefined. + */ +static inline void skip_put_bits(PutBitContext *s, int n) +{ + s->bit_left -= n; + s->buf_ptr -= 4 * (s->bit_left >> 5); + s->bit_left &= 31; +} + +/** + * Change the end of the buffer. + * + * @param size the new size in bytes of the buffer where to put bits + */ +static inline void set_put_bits_buffer_size(PutBitContext *s, int size) +{ + av_assert0(size <= INT_MAX / 8 - 32); + s->buf_end = s->buf + size; + s->size_in_bits = 8 * size; +} + +#endif /* AVCODEC_PUT_BITS_H */ diff --git a/libeplayer3-arm/external/ffmpeg/src/bitstream.c b/libeplayer3-arm/external/ffmpeg/src/bitstream.c new file mode 100644 index 0000000..b91e3e0 --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/src/bitstream.c @@ -0,0 +1,75 @@ +/* + * Common bit i/o utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2010 Loren Merritt + * + * alternative bitstream reader & writer by Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * bitstream api. + */ + +#include +#include + + +void avpriv_align_put_bits(PutBitContext *s) +{ + put_bits(s, s->bit_left & 7, 0); +} + +void avpriv_put_string(PutBitContext *pb, const char *string, + int terminate_string) +{ + while (*string) + { + put_bits(pb, 8, *string); + string++; + } + if (terminate_string) + put_bits(pb, 8, 0); +} + +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) +{ + int words = length >> 4; + int bits = length & 15; + int i; + if (length == 0) + return; + av_assert0(length <= put_bits_left(pb)); + if (words < 16 || put_bits_count(pb) & 7) + { + for (i = 0; i < words; i++) + put_bits(pb, 16, AV_RB16(src + 2 * i)); + } + else + { + for (i = 0; put_bits_count(pb) & 31; i++) + put_bits(pb, 8, src[i]); + flush_put_bits(pb); + memcpy(put_bits_ptr(pb), src + i, 2 * words - i); + skip_put_bytes(pb, 2 * words - i); + } + put_bits(pb, bits, AV_RB16(src + 2 * words) >> (16 - bits)); +} + diff --git a/libeplayer3-arm/external/ffmpeg/src/latmenc.c b/libeplayer3-arm/external/ffmpeg/src/latmenc.c new file mode 100644 index 0000000..0cf91fa --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/src/latmenc.c @@ -0,0 +1,155 @@ +/* + * LATM/LOAS muxer + * Copyright (c) 2011 Kieran Kunhya + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ +#include +#include +#include +#include + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define LATMENC_SILENT + +#ifndef LATMENC_SILENT +#define latmenc_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define latmenc_err(fmt, x...) +#endif + + +int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) +{ + MPEG4AudioConfig m4ac; + if (size > MAX_EXTRADATA_SIZE) + { + latmenc_err("Extradata is larger than currently supported.\n"); + return AVERROR_INVALIDDATA; + } + ctx->off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1); + if (ctx->off < 0) + return ctx->off; + if (ctx->object_type == AOT_ALS && (ctx->off & 7)) + { + // as long as avpriv_mpeg4audio_get_config works correctly this is impossible + latmenc_err("BUG: ALS offset is not byte-aligned\n"); + return AVERROR_INVALIDDATA; + } + /* FIXME: are any formats not allowed in LATM? */ + if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) + { + latmenc_err("Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); + return AVERROR_INVALIDDATA; + } + ctx->channel_conf = m4ac.chan_config; + ctx->object_type = m4ac.object_type; + return 0; +} + +static void latmenc_write_frame_header(LATMContext *ctx, uint8_t *extradata, int extradata_size, PutBitContext *bs) +{ + int header_size; + /* AudioMuxElement */ + put_bits(bs, 1, !!ctx->counter); + if (!ctx->counter) + { + /* StreamMuxConfig */ + put_bits(bs, 1, 0); /* audioMuxVersion */ + put_bits(bs, 1, 1); /* allStreamsSameTimeFraming */ + put_bits(bs, 6, 0); /* numSubFrames */ + put_bits(bs, 4, 0); /* numProgram */ + put_bits(bs, 3, 0); /* numLayer */ + /* AudioSpecificConfig */ + if (ctx->object_type == AOT_ALS) + { + header_size = extradata_size - (ctx->off >> 3); + avpriv_copy_bits(bs, &extradata[ctx->off >> 3], header_size); + } + else + { + // + 3 assumes not scalable and dependsOnCoreCoder == 0, + // see decode_ga_specific_config in libavcodec/aacdec.c + avpriv_copy_bits(bs, extradata, ctx->off + 3); + if (!ctx->channel_conf) + { + GetBitContext gb; + int ret = init_get_bits8(&gb, extradata, extradata_size); + av_assert0(ret >= 0); // extradata size has been checked already, so this should not fail + skip_bits_long(&gb, ctx->off + 3); + avpriv_copy_pce_data(bs, &gb); + } + } + put_bits(bs, 3, 0); /* frameLengthType */ + put_bits(bs, 8, 0xff); /* latmBufferFullness */ + put_bits(bs, 1, 0); /* otherDataPresent */ + put_bits(bs, 1, 0); /* crcCheckPresent */ + } + ctx->counter++; + ctx->counter %= ctx->mod; +} + +int latmenc_write_packet(LATMContext *ctx, uint8_t *data, int size, uint8_t *extradata, int extradata_size) +{ + PutBitContext bs; + int i, len; + if (size > 0x1fff) + goto too_large; + init_put_bits(&bs, ctx->buffer, size + 1024 + MAX_EXTRADATA_SIZE); + latmenc_write_frame_header(ctx, extradata, extradata_size, &bs); + /* PayloadLengthInfo() */ + for (i = 0; i <= size - 255; i += 255) + put_bits(&bs, 8, 255); + put_bits(&bs, 8, size - i); + /* The LATM payload is written unaligned */ + /* PayloadMux() */ + if (size && (data[0] & 0xe1) == 0x81) + { + // Convert byte-aligned DSE to non-aligned. + // Due to the input format encoding we know that + // it is naturally byte-aligned in the input stream, + // so there are no padding bits to account for. + // To avoid having to add padding bits and rearrange + // the whole stream we just remove the byte-align flag. + // This allows us to remux our FATE AAC samples into latm + // files that are still playable with minimal effort. + put_bits(&bs, 8, data[0] & 0xfe); + avpriv_copy_bits(&bs, data + 1, 8 * size - 8); + } + else + avpriv_copy_bits(&bs, data, 8 * size); + avpriv_align_put_bits(&bs); + flush_put_bits(&bs); + len = put_bits_count(&bs) >> 3; + if (len > 0x1fff) + goto too_large; + memcpy(ctx->loas_header, "\x56\xe0\x00", 3); + ctx->loas_header[1] |= (len >> 8) & 0x1f; + ctx->loas_header[2] |= len & 0xff; + ctx->len = len; + return 0; +too_large: + latmenc_err("LATM packet size larger than maximum size 0x1fff\n"); + return AVERROR_INVALIDDATA; +} + diff --git a/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c b/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c new file mode 100644 index 0000000..f07bc69 --- /dev/null +++ b/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c @@ -0,0 +1,190 @@ +/* + * MPEG-4 Audio common code + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +/** + * Parse MPEG-4 audio configuration for ALS object type. + * @param[in] gb bit reader context + * @param[in] c MPEG4AudioConfig structure to fill + * @return on success 0 is returned, otherwise a value < 0 + */ +static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c) +{ + if (get_bits_left(gb) < 112) + return -1; + if (get_bits_long(gb, 32) != MKBETAG('A', 'L', 'S', '\0')) + return -1; + // override AudioSpecificConfig channel configuration and sample rate + // which are buggy in old ALS conformance files + c->sample_rate = get_bits_long(gb, 32); + // skip number of samples + skip_bits_long(gb, 32); + // read number of channels + c->chan_config = 0; + c->channels = get_bits(gb, 16) + 1; + return 0; +} + +/* XXX: make sure to update the copies in the different encoders if you change + * this table */ +const int avpriv_mpeg4audio_sample_rates[16] = +{ + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +const uint8_t ff_mpeg4audio_channels[8] = +{ + 0, 1, 2, 3, 4, 5, 6, 8 +}; + +static inline int get_object_type(GetBitContext *gb) +{ + int object_type = get_bits(gb, 5); + if (object_type == AOT_ESCAPE) + object_type = 32 + get_bits(gb, 6); + return object_type; +} + +static inline int get_sample_rate(GetBitContext *gb, int *index) +{ + *index = get_bits(gb, 4); + return *index == 0x0f ? get_bits(gb, 24) : + avpriv_mpeg4audio_sample_rates[*index]; +} + +int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, + int bit_size, int sync_extension) +{ + GetBitContext gb; + int specific_config_bitindex, ret; + if (bit_size <= 0) + return AVERROR_INVALIDDATA; + ret = init_get_bits(&gb, buf, bit_size); + if (ret < 0) + return ret; + c->object_type = get_object_type(&gb); + c->sample_rate = get_sample_rate(&gb, &c->sampling_index); + c->chan_config = get_bits(&gb, 4); + if (c->chan_config < FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) + c->channels = ff_mpeg4audio_channels[c->chan_config]; + c->sbr = -1; + c->ps = -1; + if (c->object_type == AOT_SBR || (c->object_type == AOT_PS && + // check for W6132 Annex YYYY draft MP3onMP4 + !(show_bits(&gb, 3) & 0x03 && !(show_bits(&gb, 9) & 0x3F)))) + { + if (c->object_type == AOT_PS) + c->ps = 1; + c->ext_object_type = AOT_SBR; + c->sbr = 1; + c->ext_sample_rate = get_sample_rate(&gb, &c->ext_sampling_index); + c->object_type = get_object_type(&gb); + if (c->object_type == AOT_ER_BSAC) + c->ext_chan_config = get_bits(&gb, 4); + } + else + { + c->ext_object_type = AOT_NULL; + c->ext_sample_rate = 0; + } + specific_config_bitindex = get_bits_count(&gb); + if (c->object_type == AOT_ALS) + { + skip_bits(&gb, 5); + if (show_bits_long(&gb, 24) != MKBETAG('\0', 'A', 'L', 'S')) + skip_bits_long(&gb, 24); + specific_config_bitindex = get_bits_count(&gb); + if (parse_config_ALS(&gb, c)) + return -1; + } + if (c->ext_object_type != AOT_SBR && sync_extension) + { + while (get_bits_left(&gb) > 15) + { + if (show_bits(&gb, 11) == 0x2b7) // sync extension + { + get_bits(&gb, 11); + c->ext_object_type = get_object_type(&gb); + if (c->ext_object_type == AOT_SBR && (c->sbr = get_bits1(&gb)) == 1) + { + c->ext_sample_rate = get_sample_rate(&gb, &c->ext_sampling_index); + if (c->ext_sample_rate == c->sample_rate) + c->sbr = -1; + } + if (get_bits_left(&gb) > 11 && get_bits(&gb, 11) == 0x548) + c->ps = get_bits1(&gb); + break; + } + else + get_bits1(&gb); // skip 1 bit + } + } + //PS requires SBR + if (!c->sbr) + c->ps = 0; + //Limit implicit PS to the HE-AACv2 Profile + if ((c->ps == -1 && c->object_type != AOT_AAC_LC) || c->channels & ~0x01) + c->ps = 0; + return specific_config_bitindex; +} + +static av_always_inline unsigned int copy_bits(PutBitContext *pb, + GetBitContext *gb, + int bits) +{ + unsigned int el = get_bits(gb, bits); + put_bits(pb, bits, el); + return el; +} + +int avpriv_copy_pce_data(PutBitContext *pb, GetBitContext *gb) +{ + int five_bit_ch, four_bit_ch, comment_size, bits; + int offset = put_bits_count(pb); + copy_bits(pb, gb, 10); //Tag, Object Type, Frequency + five_bit_ch = copy_bits(pb, gb, 4); //Front + five_bit_ch += copy_bits(pb, gb, 4); //Side + five_bit_ch += copy_bits(pb, gb, 4); //Back + four_bit_ch = copy_bits(pb, gb, 2); //LFE + four_bit_ch += copy_bits(pb, gb, 3); //Data + five_bit_ch += copy_bits(pb, gb, 4); //Coupling + if (copy_bits(pb, gb, 1)) //Mono Mixdown + copy_bits(pb, gb, 4); + if (copy_bits(pb, gb, 1)) //Stereo Mixdown + copy_bits(pb, gb, 4); + if (copy_bits(pb, gb, 1)) //Matrix Mixdown + copy_bits(pb, gb, 3); + for (bits = five_bit_ch * 5 + four_bit_ch * 4; bits > 16; bits -= 16) + copy_bits(pb, gb, 16); + if (bits) + copy_bits(pb, gb, bits); + avpriv_align_put_bits(pb); + align_get_bits(gb); + comment_size = copy_bits(pb, gb, 8); + for (; comment_size > 0; comment_size--) + copy_bits(pb, gb, 8); + return put_bits_count(pb) - offset; +} diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/COPYING b/libeplayer3-arm/external/flv2mpeg4/doc/COPYING new file mode 100644 index 0000000..1e09914 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/CREDITS b/libeplayer3-arm/external/flv2mpeg4/doc/CREDITS new file mode 100644 index 0000000..d596f42 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/CREDITS @@ -0,0 +1,5 @@ +This file contains the name of the people who have contributed to +VIXY FLV Converter. The names are sorted alphabetically by last name. + +Takuma Mori (SGRA Corporation / Farside Inc. / vixy@vixy.net) + diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_CREDITS b/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_CREDITS new file mode 100644 index 0000000..0031ef8 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_CREDITS @@ -0,0 +1,46 @@ +This file contains the name of the people who have contributed to +FFmpeg. The names are sorted alphabetically by last name. + +Michel Bardiaux +Fabrice Bellard +Patrice Bensoussan +Alex Beregszaszi +BERO +Mario Brito +Ronald Bultje +Maarten Daniels +Reimar Doeffinger +Tim Ferguson +Brian Foley +Arpad Gereoffy +Philip Gladstone +Vladimir Gneushev +Roine Gustafsson +David Hammerton +Wolfgang Hesseler +Falk Hueffner +Steven Johnson +Zdenek Kabelac +Robin Kay +Todd Kirby +Nick Kurshev +Benjamin Larsson +Loïc Le Loarer +Daniel Maas +Mike Melanson +Loren Merritt +Jeff Muizelaar +Michael Niedermayer +François Revol +Peter Ross +MÃ¥ns RullgÃ¥rd +Roman Shaposhnik +Dieter Shirley +Konstantin Shishkov +Juan J. Sierralta +Ewald Snel +Sascha Sommer +Leon van Stuivenberg +Roberto Togni +Lionel Ulmer +Reynaldo Verdejo diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_IMPORTS b/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_IMPORTS new file mode 100644 index 0000000..3121ef2 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/FFMPEG_IMPORTS @@ -0,0 +1,32 @@ +VIXY FLV Converter contains the code that based on FFmpeg. +The following is the code and copyright notice. + + +/ffmpeg/libavcodec/bitstream.h + +/ffmpeg/libavcodec/bitstream.c + * Copyright (c) 2000, 2001 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + +/ffmpeg/libavcodec/h263.c + * Copyright (c) 2001 Juan J. Sierralta P. + * Copyright (c) 2002-2004 Michael Niedermayer + +/ffmpeg/libavcodec/h263data.h + +/ffmpeg/libavcodec/h263dec.c + * Copyright (c) 2001 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + +/ffmpeg/libavcodec/mpeg4data.h + +/ffmpeg/libavcodec/mpegvideo.c + * Copyright (c) 2000,2001 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + +/ffmpeg/libavcodec/mpegvideo.h + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + +And see /FFMPEG_CREDITS. +Thanks. diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/INSTALL b/libeplayer3-arm/external/flv2mpeg4/doc/INSTALL new file mode 100644 index 0000000..6be6cff --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/INSTALL @@ -0,0 +1,14 @@ +build +----- +$ cd src +$ gcc -O3 -o flv2mpeg4 avformat_writer.c dcprediction.c flv2mpeg4.c fetch.c flvdecoder.c m4vencode.c mp3header.c -lavformat -lavcodec -lavutil -I/usr/include/ffmpeg -L/usr/lib + + +usage +----- + - FLV to AVI(DIVX) + ./flv2mpeg4 input.flv output.avi + - FLV to MOV + ./flv2mpeg4 input.flv output.mov + - FLV to MP4(Video only) + ./flv2mpeg4 input.flv output.mp4 diff --git a/libeplayer3-arm/external/flv2mpeg4/doc/README b/libeplayer3-arm/external/flv2mpeg4/doc/README new file mode 100644 index 0000000..57dce64 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/doc/README @@ -0,0 +1,16 @@ +VIXY FLV Converter README +------------------------- + +1) Licensing +------------ +* Read the file COPYING and FFMPEG_IMPORTS. + +2) Intsall +---------- +* Read the file INSTALL. + +3) WebSite +---------- +* http://vixy.net/ + +Takuma Mori (vixy@vixy.net) diff --git a/libeplayer3-arm/external/flv2mpeg4/flv2mpeg4.h b/libeplayer3-arm/external/flv2mpeg4/flv2mpeg4.h new file mode 100644 index 0000000..4b273bd --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/flv2mpeg4.h @@ -0,0 +1,45 @@ +/* + * + * + * Copyright (c) 2006 vixy project + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLV_2_MPEG4_H +#define FLV_2_MPEG4_H + +#include + +typedef int (*flv2mpeg4_write_packet_cb)(void *usr_data, int keyframe, int pts, const uint8_t *buf, int size); +typedef int (*flv2mpeg4_write_extradata_cb)(void *usr_data, int width, int height, int bitrate, const uint8_t *extradata, int extradatasize); + +typedef struct +{ + flv2mpeg4_write_packet_cb write_packet_cb; + flv2mpeg4_write_extradata_cb write_extradata_cb; + void *usr_data; + void *priv; +} flv2mpeg4_CTX; + +flv2mpeg4_CTX *flv2mpeg4_init_ctx(void *priv_data, int width, int height, flv2mpeg4_write_packet_cb wp_cb, flv2mpeg4_write_extradata_cb we_cb); +void flv2mpeg4_set_frame(flv2mpeg4_CTX *ctx, int frame, int icounter); +int flv2mpeg4_process_flv_packet(flv2mpeg4_CTX *ctx, uint8_t picture_type, const uint8_t *buf, uint32_t size, uint32_t time); +int flv2mpeg4_prepare_extra_data(flv2mpeg4_CTX *ctx); +void flv2mpeg4_release_ctx(flv2mpeg4_CTX **pub_ctx); + +#endif // FLV_2_MPEG4_H \ No newline at end of file diff --git a/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h b/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h new file mode 100644 index 0000000..4b3d2c9 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h @@ -0,0 +1,177 @@ +/* + * Bitstream reader + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BITREADER_H +#define BITREADER_H + +#include "type.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _BR +{ + const uint8 *buf; + uint32 size; + uint32 read; + int bitoffset; +} BR; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void init_br(BR *p, const uint8 *buf, uint32 size) +{ + p->buf = buf; + p->size = size; + p->read = 0; + p->bitoffset = 0; +} + +static uint8 get_u8(BR *p) +{ + return p->buf[p->read++]; +} + +static uint32 get_u24(BR *p) +{ + uint32 a = get_u8(p); + uint32 b = get_u8(p); + uint32 c = get_u8(p); + return (a << 16) | (b << 8) | c; +} + +static uint32 get_u32(BR *p) +{ + uint32 a = get_u8(p); + uint32 b = get_u8(p); + uint32 c = get_u8(p); + uint32 d = get_u8(p); + return (a << 24) | (b << 16) | (c << 8) | d; +} + +static int is_eob(BR *p) +{ + return p->read >= p->size; +} + +static void skip(BR *p, uint32 skip) +{ + p->read += skip; +} + +static uint32 show_bits(BR *p, uint32 bits) +{ + const uint8 *pp; + uint32 tmp; + pp = p->buf + p->read; + tmp = (pp[0] << 24) | (pp[1] << 16) | (pp[2] << 8) | (pp[3]); + tmp <<= p->bitoffset; + tmp >>= 32 - bits; + return tmp; +} + +static int32 show_sbits(BR *p, uint32 bits) +{ + const uint8 *pp; + int32 tmp; + pp = p->buf + p->read; + tmp = (pp[0] << 24) | (pp[1] << 16) | (pp[2] << 8) | (pp[3]); + tmp <<= p->bitoffset; + tmp >>= 32 - bits; + return tmp; +} + +static void flash_bits(BR *p, uint32 bits) +{ + if (bits > 0) + { + bits = bits + p->bitoffset; + p->read += bits >> 3; + p->bitoffset = bits & 7; + } +} + +static uint32 get_bits(BR *p, uint32 bits) +{ + uint32 tmp = show_bits(p, bits); + flash_bits(p, bits); + return tmp; +} + +static int32 get_sbits(BR *p, uint32 bits) +{ + int32 tmp = show_sbits(p, bits); + flash_bits(p, bits); + return tmp; +} + +static void align_bits(BR *p) +{ + if (p->bitoffset > 0) + { + p->bitoffset = 0; + p->read++; + } +} + +static int __inline get_br_pos(BR *p) +{ + return (p->read << 3) + p->bitoffset; +} + +typedef struct _VLCtab +{ + int code; + int n; +} VLCtab; + +static int __inline get_vlc(BR *br, const VLCtab *table, int bits, int max_depth) +{ + int n, index, nb_bits, code; + index = show_bits(br, bits); + code = table[index].code; + n = table[index].n; + if (max_depth > 1 && n < 0) + { + flash_bits(br, bits); + nb_bits = -n; + index = show_bits(br, nb_bits) + code; + code = table[index].code; + n = table[index].n; + } + flash_bits(br, n); + return code; +} + +static int __inline get_vlcdec(BR *p, const VLCtab *table, int bits, int max_depth, VLCDEC *vlcdec) +{ + int pos = get_br_pos(p); + uint32 show = show_bits(p, 24); + uint32 tmp = get_vlc(p, table, bits, max_depth); + int len = get_br_pos(p) - pos; + int val = show >> (24 - len); + vlcdec->bits = len; + vlcdec->value = val; + return tmp; +} + +#endif // BITREADER_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h b/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h new file mode 100644 index 0000000..3e76f36 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h @@ -0,0 +1,144 @@ +/* + * Bitstream writer + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BITWRITER_H +#define BITWRITER_H + +#include "type.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _BW +{ + uint8 *buf; + uint32 size; + uint32 pos; + uint32 bitoffset; + uint32 tmp; + +} BW; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void __inline clear_bw(BW *p) +{ + p->pos = 0; + p->bitoffset = 0; + p->tmp = 0; +} + +static void __inline init_bw(BW *p, uint8 *buf, uint32 size) +{ + p->buf = buf; + p->size = size; + clear_bw(p); +} + +static void __inline forword_bits(BW *p, uint32 bits) +{ + p->bitoffset += bits; + if (p->bitoffset >= 32) + { + p->buf[p->pos++] = (p->tmp >> 24) & 0xff; + p->buf[p->pos++] = (p->tmp >> 16) & 0xff; + p->buf[p->pos++] = (p->tmp >> 8) & 0xff; + p->buf[p->pos++] = (p->tmp >> 0) & 0xff; + p->tmp = 0; + p->bitoffset -= 32; + } +} + +static void __inline put_bits(BW *p, uint32 bits, uint32 value) +{ + uint32 shift = 32 - p->bitoffset - bits; + if (shift <= 32) + { + p->tmp |= value << shift; + forword_bits(p, bits); + } + else + { + shift = bits - (32 - p->bitoffset); + p->tmp |= value >> shift; + forword_bits(p, bits - shift); + p->tmp |= value << (32 - shift); + forword_bits(p, shift); + } +} + +static void __inline pad_to_boundary(BW *p) +{ + uint32 bits = 8 - (p->bitoffset % 8); + if (bits < 8) + { + put_bits(p, bits, 0); + } +} + +static void __inline flash_bw(BW *p) +{ + pad_to_boundary(p); + switch (p->bitoffset) + { + case 0: // nothing to do + break; + case 8: + p->buf[p->pos++] = (p->tmp >> 24) & 0xff; + break; + case 16: + p->buf[p->pos++] = (p->tmp >> 24) & 0xff; + p->buf[p->pos++] = (p->tmp >> 16) & 0xff; + break; + case 24: + p->buf[p->pos++] = (p->tmp >> 24) & 0xff; + p->buf[p->pos++] = (p->tmp >> 16) & 0xff; + p->buf[p->pos++] = (p->tmp >> 8) & 0xff; + break; + default: +// fprintf(stderr, "flash_bw error!(%d)\n", p->bitoffset); + break; + } + p->tmp = 0; + p->bitoffset = 0; +} + +static uint32 __inline get_bw_pos(BW *p) +{ + return p->pos * 8 + p->bitoffset; +} + +static void __inline put_vlcdec(BW *bw, VLCDEC *vlcdec) +{ + put_bits(bw, vlcdec->bits, vlcdec->value); +} + +// M4V ADDED +static void __inline m4v_stuffing(BW *p) +{ + int length; + put_bits(p, 1, 0); + length = (- p->bitoffset) & 7; + if (length) put_bits(p, length, (1 << length) - 1); +} + +#endif // BITWRITER_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c new file mode 100644 index 0000000..66f348f --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c @@ -0,0 +1,183 @@ +/* + * DC prediction + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dcprediction.h" + + +// M4V ADDED +static const uint8 mpeg4_y_dc_scale_table[32] = +{ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 8, 8, 8, 8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 38, 40, 42, 44, 46 +}; + +// M4V ADDED +static const uint8 mpeg4_c_dc_scale_table[32] = +{ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 +}; + +static int __inline get_pred(int *dc_cur, int stride, int scale) +{ + /* B C + A X */ + int A = dc_cur[-1]; + int B = dc_cur[-1 - stride]; + int C = dc_cur[-stride]; + int pred; + if (abs(A - B) < abs(B - C)) + { + pred = C; + } + else + { + pred = A; + } + return (pred + (scale >> 1)) / scale; +} + +static void __inline set_dc_to_dc_cur(int *dc_cur, int level, int scale) +{ + level *= scale; + if (level & (~2047)) + { + if (level < 0) + level = 0; + else + level = 2047; + } + dc_cur[0] = level; +} + +static int *get_dc_cur(M4V_DCPRED *pred, int mb_x, int mb_y, int n) +{ + if (n < 4) + { + return pred->dc[n] + mb_x * 2 + mb_y * 2 * pred->stride[n] + pred->block_offset[n]; + } + else + { + return pred->dc[n] + mb_x * 1 + mb_y * pred->stride[n]; + } +} + +static int __inline get_scale(M4V_DCPRED *pred, int n) +{ + if (n < 4) + { + return pred->y_dc_scale; + } + else + { + return pred->c_dc_scale; + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void dcpred_set_qscale(M4V_DCPRED *pred, int qscale) +{ + if (qscale < 0) qscale = 0; + if (qscale > 31) qscale = 31; + pred->y_dc_scale = mpeg4_y_dc_scale_table[qscale]; + pred->c_dc_scale = mpeg4_c_dc_scale_table[qscale]; +} + +void dcpred_set_pos(M4V_DCPRED *pred, int mb_x, int mb_y) +{ + int n; + for (n = 0; n < 6; n++) + { + pred->dc_cur[n] = get_dc_cur(pred, mb_x, mb_y, n); + } +} + +int dcpred_for_enc(M4V_DCPRED *p, int n, int level) +{ + int *dc_cur = p->dc_cur[n]; + int scale = get_scale(p, n); + int pred = get_pred(dc_cur, p->stride[n], scale); + set_dc_to_dc_cur(dc_cur, level, scale); + return level - pred; +} + +int dcpred_for_dec(M4V_DCPRED *p, int n, int level) +{ + int *dc_cur = p->dc_cur[n]; + int scale = get_scale(p, n); + int pred = get_pred(dc_cur, p->stride[n], scale); + level += pred; + set_dc_to_dc_cur(dc_cur, level, scale); + return level; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void init_plane(M4V_DCPRED *pred, int n) +{ + int x, len = pred->stride[n] * pred->height[n]; + int *p = pred->_dc[n]; + for (x = 0; x < len; x++) + { + p[x] = 1024; + } +} + +void init_dcpred(M4V_DCPRED *pred) +{ + init_plane(pred, 0); + init_plane(pred, 4); + init_plane(pred, 5); +} + +void alloc_dcpred(M4V_DCPRED *pred, int mb_width, int mb_height) +{ + const int w2 = mb_width * 2 + 1; + const int h2 = mb_height * 2 + 1; + const int w = mb_width + 1; + const int h = mb_height + 1; + pred->_dc[0] = pred->_dc[1] = pred->_dc[2] = pred->_dc[3] = (int *)malloc(sizeof(int) * w2 * h2); + pred->_dc[4] = (int *)malloc(sizeof(int) * w * h); + pred->_dc[5] = (int *)malloc(sizeof(int) * w * h); + pred->dc[0] = pred->dc[1] = pred->dc[2] = pred->dc[3] = pred->_dc[0] + w2 + 1; + pred->dc[4] = pred->_dc[4] + w + 1; + pred->dc[5] = pred->_dc[5] + w + 1; + pred->stride[0] = pred->stride[1] = pred->stride[2] = pred->stride[3] = w2; + pred->height[0] = pred->height[1] = pred->height[2] = pred->height[3] = h2; + pred->stride[4] = pred->stride[5] = w; + pred->height[4] = pred->height[5] = h; + pred->block_offset[0] = 0; + pred->block_offset[1] = 1; + pred->block_offset[2] = w2; + pred->block_offset[3] = w2 + 1; + pred->block_offset[4] = 0; + pred->block_offset[5] = 0; +} + +void free_dcpred(M4V_DCPRED *pred) +{ + free(pred->_dc[0]); + free(pred->_dc[4]); + free(pred->_dc[5]); +} diff --git a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h new file mode 100644 index 0000000..936b741 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h @@ -0,0 +1,56 @@ +/* + * DC Prediction + * + * Copyright (c) 2006 vixy project + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DCPREDICTION_H +#define DCPREDICTION_H + +#include "type.h" +#include + +typedef struct _M4V_DCPRED +{ + int *_dc[6]; // for malloc(),free() + int *dc[6]; // for point (0,0) + int *dc_cur[6]; // for point current pos + + int stride[6]; + int height[6]; + + int block_offset[6]; + + int y_dc_scale; + int c_dc_scale; + + +} M4V_DCPRED; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void dcpred_set_qscale(M4V_DCPRED *pred, int qscale); +void dcpred_set_pos(M4V_DCPRED *pred, int mb_x, int mb_y); +int dcpred_for_enc(M4V_DCPRED *pred, int n, int level); +int dcpred_for_dec(M4V_DCPRED *pred, int n, int level); +void init_dcpred(M4V_DCPRED *pred); +void alloc_dcpred(M4V_DCPRED *pred, int mb_width, int mb_height); +void free_dcpred(M4V_DCPRED *pred); + +#endif // DCPREDICTION_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flv.h b/libeplayer3-arm/external/flv2mpeg4/src/flv.h new file mode 100644 index 0000000..e2f08ce --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/flv.h @@ -0,0 +1,161 @@ +/* + * FLV structs and tables + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLV_H +#define FLV_H + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include "bitreader.h" +#include "bitwriter.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _BLOCK +{ + int block[64]; + + int index; + int last_index; + +} BLOCK; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _MICROBLOCK +{ + BLOCK block[6]; + int dquant; + + int intra; + int skip; +#define MV_TYPE_16X16 0 +#define MV_TYPE_8X8 1 + int mv_type; + VLCDEC mv_x[4]; + VLCDEC mv_y[4]; + +} MICROBLOCK; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _PICTURE +{ + int width; + int height; + + +#define FLV_I_TYPE 0 +#define FLV_P_TYPE 1 + + int picture_type; // 0:I 1:P + int escape_type; // 0:h263 1:flv(11bits) + + int qscale; + + int frame_number; + +} PICTURE; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int decode_picture_header(BR *p, PICTURE *picture); +int decode_I_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale); +int decode_P_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale); + +void encode_picture_header(BW *bw, PICTURE *picture); +void encode_I_mb(BW *bw, MICROBLOCK *mb, int escape_type); +void encode_P_mb(BW *bw, MICROBLOCK *mb, int escape_type); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static const uint16 rl_inter_vlc[103][2] = +{ + { 0x2, 2 }, { 0xf, 4 }, { 0x15, 6 }, { 0x17, 7 }, + { 0x1f, 8 }, { 0x25, 9 }, { 0x24, 9 }, { 0x21, 10 }, + { 0x20, 10 }, { 0x7, 11 }, { 0x6, 11 }, { 0x20, 11 }, + { 0x6, 3 }, { 0x14, 6 }, { 0x1e, 8 }, { 0xf, 10 }, + { 0x21, 11 }, { 0x50, 12 }, { 0xe, 4 }, { 0x1d, 8 }, + { 0xe, 10 }, { 0x51, 12 }, { 0xd, 5 }, { 0x23, 9 }, + { 0xd, 10 }, { 0xc, 5 }, { 0x22, 9 }, { 0x52, 12 }, + { 0xb, 5 }, { 0xc, 10 }, { 0x53, 12 }, { 0x13, 6 }, + { 0xb, 10 }, { 0x54, 12 }, { 0x12, 6 }, { 0xa, 10 }, + { 0x11, 6 }, { 0x9, 10 }, { 0x10, 6 }, { 0x8, 10 }, + { 0x16, 7 }, { 0x55, 12 }, { 0x15, 7 }, { 0x14, 7 }, + { 0x1c, 8 }, { 0x1b, 8 }, { 0x21, 9 }, { 0x20, 9 }, + { 0x1f, 9 }, { 0x1e, 9 }, { 0x1d, 9 }, { 0x1c, 9 }, + { 0x1b, 9 }, { 0x1a, 9 }, { 0x22, 11 }, { 0x23, 11 }, + { 0x56, 12 }, { 0x57, 12 }, { 0x7, 4 }, { 0x19, 9 }, + { 0x5, 11 }, { 0xf, 6 }, { 0x4, 11 }, { 0xe, 6 }, + { 0xd, 6 }, { 0xc, 6 }, { 0x13, 7 }, { 0x12, 7 }, + { 0x11, 7 }, { 0x10, 7 }, { 0x1a, 8 }, { 0x19, 8 }, + { 0x18, 8 }, { 0x17, 8 }, { 0x16, 8 }, { 0x15, 8 }, + { 0x14, 8 }, { 0x13, 8 }, { 0x18, 9 }, { 0x17, 9 }, + { 0x16, 9 }, { 0x15, 9 }, { 0x14, 9 }, { 0x13, 9 }, + { 0x12, 9 }, { 0x11, 9 }, { 0x7, 10 }, { 0x6, 10 }, + { 0x5, 10 }, { 0x4, 10 }, { 0x24, 11 }, { 0x25, 11 }, + { 0x26, 11 }, { 0x27, 11 }, { 0x58, 12 }, { 0x59, 12 }, + { 0x5a, 12 }, { 0x5b, 12 }, { 0x5c, 12 }, { 0x5d, 12 }, + { 0x5e, 12 }, { 0x5f, 12 }, { 0x3, 7 }, +}; + +static const int8 rl_inter_level[102] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 1, 2, 3, 4, + 5, 6, 1, 2, 3, 4, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 3, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +static const int8 rl_inter_run[102] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 0, 1, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static const int rl_inter_n = 102; +static const int rl_inter_last = 58; + + +#endif // FLV_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c b/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c new file mode 100644 index 0000000..9839aab --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c @@ -0,0 +1,289 @@ +/* + * FLV to MPEG4 converter + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "m4v.h" +#include "bitwriter.h" +#include "flv.h" +#include "m4vencode.h" +#include "../flv2mpeg4.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _CONVCTX +{ + int width; + int height; + + int frame; + int icounter; + + M4V_VOL vol; +} CONVCTX; + + +typedef struct +{ + uint8 *out_buf; + M4V_VOL vol; + CONVCTX conv; +} CTX; + +#define VOL_TIME_BITS 5 +#define PACKETBUFFER_SIZE (256*1024*4) + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static const uint8 ff_mpeg4_y_dc_scale_table[32] = +{ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 8, 8, 8, 8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 38, 40, 42, 44, 46 +}; + +static const uint8 ff_mpeg4_c_dc_scale_table[32] = +{ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 +}; + + +static void copy_vol(PICTURE *flv_pic, M4V_VOL *vol) +{ + vol->width = flv_pic->width; + vol->height = flv_pic->height; + vol->time_bits = VOL_TIME_BITS; // 0-31 +} + +static void copy_vop(PICTURE *flv_pic, M4V_VOP *vop, CONVCTX *c) +{ + vop->qscale = flv_pic->qscale; + vop->time = c->frame % 30; + vop->icount = (c->icounter + 29) / 30; + vop->intra_dc_threshold = 99; + if (flv_pic->picture_type == FLV_I_TYPE) + { + vop->picture_type = M4V_I_TYPE; + } + else + { + vop->picture_type = M4V_P_TYPE; + vop->f_code = 1; + } +} + +static void copy_microblock(MICROBLOCK *flv_mb, M4V_MICROBLOCK *m4v_mb) +{ + int i; + m4v_mb->dquant = flv_mb->dquant; + memcpy(m4v_mb->block, flv_mb->block, sizeof(m4v_mb->block)); // !!!!!!! + m4v_mb->intra = flv_mb->intra; + m4v_mb->skip = flv_mb->skip; + m4v_mb->mv_type = flv_mb->mv_type; + memcpy(m4v_mb->mv_x, flv_mb->mv_x, sizeof(m4v_mb->mv_x)); // !!!!!! + memcpy(m4v_mb->mv_y, flv_mb->mv_y, sizeof(m4v_mb->mv_y)); // !!!!!! + // dc rescale + if (m4v_mb->intra) + { + for (i = 0; i < 4; i++) + { + m4v_mb->block[i].block[0] *= 8; + m4v_mb->block[i].block[0] /= ff_mpeg4_y_dc_scale_table[m4v_mb->qscale]; + } + for (i = 4; i < 6; i++) + { + m4v_mb->block[i].block[0] *= 8; + m4v_mb->block[i].block[0] /= ff_mpeg4_c_dc_scale_table[m4v_mb->qscale]; + } + } +} + +static int write_pad_not_coded_frames(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BW *bw, uint32 time) +{ + // if any timecode padding is needed, then pad. + while (c->frame * 1000 / 30 < time) + { + M4V_VOP vop; + memset(&vop, 0, sizeof(vop)); + vop.picture_type = M4V_P_TYPE; + vop.time = c->frame % 30; + vop.icount = (c->icounter + 29) / 30; + m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 1); + m4v_stuffing(bw); + flash_bw(bw); + // write frame + if (pub_ctx->write_packet_cb(pub_ctx->usr_data, + 0, + 0,//c->frame, + bw->buf, + bw->pos) < 0) + { + return -1; + } + clear_bw(bw); + c->frame++; + c->icounter++; + } + return 0; +} + +static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, PICTURE *flvpic, uint32 time) +{ + MICROBLOCK mb; + M4V_VOP vop; + M4V_MICROBLOCK m4v_mb; + int x, y; + int mb_width = (flvpic->width + 15) / 16; + int mb_height = (flvpic->height + 15) / 16; + memset(&vop, 0, sizeof(vop)); + copy_vop(flvpic, &vop, c); + m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 0); + // transcode flv to mpeg4 + for (y = 0; y < mb_height; y++) + { + for (x = 0; x < mb_width; x++) + { + memset(&mb, 0, sizeof(mb)); + memset(&m4v_mb, 0, sizeof(m4v_mb)); + if (vop.picture_type == M4V_I_TYPE) + { + mb.intra = 1; + if (decode_I_mb(br, &mb, flvpic->escape_type, flvpic->qscale) < 0) return -1; + m4v_mb.qscale = vop.qscale; + copy_microblock(&mb, &m4v_mb); + m4v_encode_I_dcpred(&m4v_mb, &c->vol.dcpred, x, y); + m4v_encode_I_mb(bw, &m4v_mb); + } + else + { + if (decode_P_mb(br, &mb, flvpic->escape_type, flvpic->qscale) < 0) return -1; + m4v_mb.qscale = vop.qscale; + copy_microblock(&mb, &m4v_mb); + m4v_encode_I_dcpred(&m4v_mb, &c->vol.dcpred, x, y); + m4v_encode_P_mb(bw, &m4v_mb); + } + } + } + m4v_stuffing(bw); + flash_bw(bw); + // write frame + if (pub_ctx->write_packet_cb(pub_ctx->usr_data, + vop.picture_type == M4V_I_TYPE, + 0,//c->frame, + bw->buf, + bw->pos) < 0) + { + return -1; + } + c->frame++; + c->icounter++; + return 0; +} + +static int write_m4v_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, uint32 time) +{ + PICTURE picture; + memset(&picture, 0, sizeof(picture)); + init_dcpred(&c->vol.dcpred); + if (decode_picture_header(br, &picture) < 0) return -1; + if (c->width != picture.width || c->height != picture.height) return -1; //size changed.. + copy_vol(&picture, &c->vol); + if (picture.picture_type == FLV_I_TYPE) + { + c->icounter = 0; + } + else + { + if (write_pad_not_coded_frames(pub_ctx, c, bw, time) < 0) return -1; + } + if (write_m4v_picture_frame(pub_ctx, c, br, bw, &picture, time) < 0) + { + return -1; + } + return 0; +} + +int flv2mpeg4_process_flv_packet(flv2mpeg4_CTX *ctx, uint8 picture_type, const uint8 *buf, uint32 size, uint32 time) +{ + CTX *p = ctx->priv; + BR br; + BW bw; + init_br(&br, buf, size); + init_bw(&bw, p->out_buf, PACKETBUFFER_SIZE); + write_m4v_frame(ctx, &p->conv, &br, &bw, time); + return 0; +} + +int flv2mpeg4_prepare_extra_data(flv2mpeg4_CTX *ctx) +{ + CTX *p = ctx->priv; + BW bw; + CONVCTX *c = &(p->conv); + M4V_VOP vop; + memset(&vop, 0, sizeof(vop)); + init_bw(&bw, p->out_buf, PACKETBUFFER_SIZE); + c->vol.width = c->width; + c->vol.height = c->height; + c->vol.time_bits = VOL_TIME_BITS; // 0-31 + m4v_encode_m4v_header(&bw, &c->vol, 0); + m4v_stuffing(&bw); + flash_bw(&bw); + alloc_dcpred(&c->vol.dcpred, (c->width + 15) / 16, (c->height + 15) / 16); + return ctx->write_extradata_cb(ctx->usr_data, c->width, c->height, 200 * 1000, bw.buf, bw.pos); +} + +void flv2mpeg4_set_frame(flv2mpeg4_CTX *ctx, int frame, int icounter) +{ + CTX *p = ctx->priv; + p->conv.frame = frame; + p->conv.icounter = icounter; +} + +flv2mpeg4_CTX *flv2mpeg4_init_ctx(void *priv_data, int width, int height, flv2mpeg4_write_packet_cb wp_cb, flv2mpeg4_write_extradata_cb we_cb) +{ + flv2mpeg4_CTX *pub_ctx = malloc(sizeof(flv2mpeg4_CTX)); + memset(pub_ctx, 0x0, sizeof(flv2mpeg4_CTX)); + pub_ctx->usr_data = priv_data; + pub_ctx->write_packet_cb = wp_cb; + pub_ctx->write_extradata_cb = we_cb; + pub_ctx->priv = malloc(sizeof(CTX)); + memset(pub_ctx->priv, 0x0, sizeof(CTX)); + CTX *ctx = pub_ctx->priv; + ctx->conv.width = width; + ctx->conv.height = height; + ctx->out_buf = malloc(PACKETBUFFER_SIZE); + memset(ctx->out_buf, 0x0, PACKETBUFFER_SIZE); + memset(&(ctx->vol), 0x0, sizeof(ctx->vol)); + return pub_ctx; +} + +void flv2mpeg4_release_ctx(flv2mpeg4_CTX **pub_ctx) +{ + CTX *ctx = (*pub_ctx)->priv; + free_dcpred(&ctx->conv.vol.dcpred); + free(ctx->out_buf); + free(ctx); + free(*pub_ctx); + *pub_ctx = NULL; +} + + + diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c b/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c new file mode 100644 index 0000000..2642a28 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c @@ -0,0 +1,523 @@ +/* + * FLV Bitstream/VLC Decoder + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include "bitreader.h" +#include "flv.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static const uint8 zig_zag_scan[64] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + + +static const VLCtab vlc_table_intra_MCBPC[] = //: table_size=72 table_allocated=128 bits=6 +{ + {64, -3}, + {5, 6}, {6, 6}, {7, 6}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {1, 3}, {1, 3}, {1, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {3, 3}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {-1, 0}, {8, 3}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0} +}; + +static const VLCtab vlc_table_inter_MCBPC[] = //table_size=198 table_allocated=256 bits=7 +{ + {128, -6}, {192, -2}, {196, -1}, {7, 7}, {18, 7}, {17, 7}, {10, 7}, {9, 7}, {12, 6}, {12, 6}, {3, 6}, {3, 6}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, {2, 4}, {2, 4}, {2, 4}, {2, 4}, {2, 4}, {2, 4}, {2, 4}, {2, 4}, {1, 4}, {1, 4}, + {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, + {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {16, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, + {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {8, 3}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, + {-1, 0}, {24, 4}, {24, 4}, {24, 4}, {24, 4}, {25, 6}, {-1, 0}, {26, 6}, {27, 6}, {20, 2}, {20, 2}, {20, 2}, + {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, {20, 2}, + {20, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, + {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, + {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {14, 2}, {13, 2}, {11, 2}, {6, 1}, + {6, 1}, {5, 1}, {19, 1}, +}; + +static const VLCtab vlc_table_cbpy[] = //table_size=64 table_allocated=64 bits=6 +{ + {-1, 0}, {-1, 0}, {6, 6}, {9, 6}, {8, 5}, {8, 5}, {4, 5}, {4, 5}, {2, 5}, {2, 5}, {1, 5}, {1, 5}, {0, 4}, {0, 4}, + {0, 4}, {0, 4}, {12, 4}, {12, 4}, {12, 4}, {12, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {14, 4}, {14, 4}, + {14, 4}, {14, 4}, {5, 4}, {5, 4}, {5, 4}, {5, 4}, {13, 4}, {13, 4}, {13, 4}, {13, 4}, {3, 4}, {3, 4}, {3, 4}, + {3, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {7, 4}, {7, 4}, {7, 4}, {7, 4}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, + {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2}, {15, 2} +}; + +static const VLCtab vlc_table_rl_inter[] = //: table_size=554 table_allocated=1024 bits=9 +{ + {-1, 0}, {512, -2}, {516, -1}, {518, -1}, {520, -1}, {522, -1}, {524, -1}, {526, -1}, {528, -2}, {532, -2}, + {536, -3}, {544, -3}, {102, 7}, {102, 7}, {102, 7}, {102, 7}, {552, -1}, {85, 9}, {84, 9}, {83, 9}, {82, 9}, + {81, 9}, {80, 9}, {79, 9}, {78, 9}, {59, 9}, {53, 9}, {52, 9}, {51, 9}, {50, 9}, {49, 9}, {48, 9}, {47, 9}, + {46, 9}, {26, 9}, {23, 9}, {6, 9}, {5, 9}, {77, 8}, {77, 8}, {76, 8}, {76, 8}, {75, 8}, {75, 8}, {74, 8}, + {74, 8}, {73, 8}, {73, 8}, {72, 8}, {72, 8}, {71, 8}, {71, 8}, {70, 8}, {70, 8}, {45, 8}, {45, 8}, {44, 8}, + {44, 8}, {19, 8}, {19, 8}, {14, 8}, {14, 8}, {4, 8}, {4, 8}, {69, 7}, {69, 7}, {69, 7}, {69, 7}, {68, 7}, + {68, 7}, {68, 7}, {68, 7}, {67, 7}, {67, 7}, {67, 7}, {67, 7}, {66, 7}, {66, 7}, {66, 7}, {66, 7}, {43, 7}, + {43, 7}, {43, 7}, {43, 7}, {42, 7}, {42, 7}, {42, 7}, {42, 7}, {40, 7}, {40, 7}, {40, 7}, {40, 7}, {3, 7}, + {3, 7}, {3, 7}, {3, 7}, {65, 6}, {65, 6}, {65, 6}, {65, 6}, {65, 6}, {65, 6}, {65, 6}, {65, 6}, {64, 6}, {64, 6}, + {64, 6}, {64, 6}, {64, 6}, {64, 6}, {64, 6}, {64, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, + {63, 6}, {63, 6}, {61, 6}, {61, 6}, {61, 6}, {61, 6}, {61, 6}, {61, 6}, {61, 6}, {61, 6}, {38, 6}, {38, 6}, + {38, 6}, {38, 6}, {38, 6}, {38, 6}, {38, 6}, {38, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, + {36, 6}, {36, 6}, {34, 6}, {34, 6}, {34, 6}, {34, 6}, {34, 6}, {34, 6}, {34, 6}, {34, 6}, {31, 6}, {31, 6}, + {31, 6}, {31, 6}, {31, 6}, {31, 6}, {31, 6}, {31, 6}, {13, 6}, {13, 6}, {13, 6}, {13, 6}, {13, 6}, {13, 6}, + {13, 6}, {13, 6}, {2, 6}, {2, 6}, {2, 6}, {2, 6}, {2, 6}, {2, 6}, {2, 6}, {2, 6}, {28, 5}, {28, 5}, {28, 5}, + {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, + {28, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, + {25, 5}, {25, 5}, {25, 5}, {25, 5}, {25, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, + {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {22, 5}, {58, 4}, {58, 4}, {58, 4}, + {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, + {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, + {58, 4}, {58, 4}, {58, 4}, {58, 4}, {58, 4}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, + {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, + {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, + {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, + {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, + {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {12, 3}, {18, 4}, + {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, + {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, + {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {18, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, + {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, + {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {1, 4}, {62, 2}, {60, 2}, + {10, 2}, {9, 2}, {89, 1}, {88, 1}, {87, 1}, {86, 1}, {39, 1}, {37, 1}, {35, 1}, {32, 1}, {29, 1}, {24, 1}, + {20, 1}, {15, 1}, {11, 2}, {16, 2}, {54, 2}, {55, 2}, {90, 2}, {91, 2}, {92, 2}, {93, 2}, {17, 3}, {21, 3}, + {27, 3}, {30, 3}, {33, 3}, {41, 3}, {56, 3}, {57, 3}, {94, 3}, {95, 3}, {96, 3}, {97, 3}, {98, 3}, {99, 3}, + {100, 3}, {101, 3}, {8, 1}, {7, 1} +}; + + +static const VLCtab vlc_table_mv[] = //mv_vlc: table_size=538 table_allocated=1024 bits=9 +{ + {512, -3}, {520, -2}, {524, -1}, {526, -1}, {528, -1}, {530, -1}, {532, -1}, {534, -1}, {536, -1}, {10, 9}, + {9, 9}, {8, 9}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, + {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, + {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {-1, 0}, {-1, 0}, + {32, 3}, {31, 3}, {30, 2}, {30, 2}, {29, 2}, {29, 2}, {28, 2}, {27, 2}, {26, 2}, {25, 2}, {24, 1}, {23, 1}, {22, 1}, + {21, 1}, {20, 1}, {19, 1}, {18, 1}, {17, 1}, {16, 1}, {15, 1}, {14, 1}, {13, 1}, {12, 1}, {11, 1}, +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int __inline decode_DC(BR *p) +{ + int level = get_bits(p, 8); + if ((level & 0x7f) == 0) + { + printf("illigal dc\n"); + return -1; + } + if (level == 255) level = 128; +// printf("DC: %d\n", level); + return level; +} + +static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i) +{ + int code, run, level, last, sign; + while (1) + { + code = get_vlc(p, vlc_table_rl_inter, 9, 2); + if (code < 0) + { + printf("invalid Huffman code in getblock()\n"); + return -1; + } + if (code == rl_inter_n) + { + //escape + if (escape_type == 1) + { + int is11bit = get_bits(p, 1); + last = get_bits(p, 1); + run = get_bits(p, 6); + if (is11bit) + { + level = get_sbits(p, 11); + } + else + { + level = get_sbits(p, 7); + } + } + else + { + last = get_bits(p, 1); + run = get_bits(p, 6); + level = get_bits(p, 8); + sign = level >= 128; + if (sign) level = 256 - level; + } + } + else + { + run = rl_inter_run[code]; + level = rl_inter_level[code]; + last = code >= rl_inter_last; + sign = get_bits(p, 1); + if (sign) level = -level; + } + i += run; + if (i >= 64) + { + printf("run overflow..\n"); + return -1; + } + block->block[zig_zag_scan[i]] = level; + if (last) break; + i++; + } + block->last_index = i; + return 0; +} + +static int __inline decode_intra_block(BR *p, BLOCK *block, int escape_type, int coded) +{ + int level = decode_DC(p); + if (level < 0) + { + printf("dc error.\n"); + return -1; + } + block->block[0] = level; + block->last_index = 0; + if (!coded) + { + return 0; + } + if (decode_AC(p, block, escape_type, 1) < 0) return -1; + return 0; +} + +static int __inline decode_inter_block(BR *p, BLOCK *block, int escape_type, int coded) +{ + block->last_index = -1; + if (!coded) + { + return 0; + } + if (decode_AC(p, block, escape_type, 0) < 0) return -1; + return 0; +} + +static int __inline get_intra_MCBPC(BR *br) +{ + int cbpc; + do + { + cbpc = get_vlc(br, vlc_table_intra_MCBPC, 6, 2); + if (cbpc < 0) return -1; + } + while (cbpc == 8); + return cbpc; +} + +static int __inline get_inter_MCBPC(BR *br) +{ + int cbpc; + do + { + if (get_bits(br, 1)) + { + return -2; + } + cbpc = get_vlc(br, vlc_table_inter_MCBPC, 7, 2); + if (cbpc < 0) return -1; + } + while (cbpc == 20); + return cbpc; +} + +static int __inline get_cbpy(BR *br) +{ + return get_vlc(br, vlc_table_cbpy, 6, 1); +} + +static int __inline decode_dquant(BR *p) +{ + static const int table[4] = { -1, -2, 1, 2 }; + return table[get_bits(p, 2)]; +} + +static int __inline decode_motion(BR *br, VLCDEC *vlcdec) +{ + int tmp; + int code = get_vlcdec(br, vlc_table_mv, 9, 2, vlcdec); + vlcdec->bits_ex = 0; + if (code == 0) + return 0; + if (code < 0) + return -1; + tmp = get_bits(br, 1); + /* + vlcdec->value |= (tmp << vlcdec->bits); + /// vlcdec->value <<= 1; + // vlcdec->value |= tmp; + vlcdec->bits++; + // vlcdec->value |= (tmp << vlcdec->bits); + */ + vlcdec->bits_ex = 1; + vlcdec->value_ex = tmp; + return 0; +} + +static int __inline decode_intra_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant) +{ + int cbpy, cbp; + int i; + cbpy = get_cbpy(p); + if (cbpy < 0) + { + printf("cbpy error\n"); + return -1; + } + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) + { + mb->dquant = decode_dquant(p); + qscale += mb->dquant; + } + for (i = 0; i < 6; i++) + { + if (decode_intra_block(p, &mb->block[i], escape_type, cbp & 32) != 0) return -1; + cbp += cbp; + } + return 0; +} + +static int __inline decode_inter_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant) +{ + int cbpy, cbp; + int i; + cbpy = get_cbpy(p); + if (cbpy < 0) + { + printf("cbpy error\n"); + return -1; + } + cbpy ^= 0xF; + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) + { + mb->dquant = decode_dquant(p); + qscale += mb->dquant; + } + if ((cbpc & 16) == 0) + { + // 16x16 motion prediction + decode_motion(p, &mb->mv_x[0]); + decode_motion(p, &mb->mv_y[0]); + mb->mv_type = MV_TYPE_16X16; + } + else + { + // 8x8 motion prediction + for (i = 0; i < 4; i++) + { + decode_motion(p, &mb->mv_x[i]); + decode_motion(p, &mb->mv_y[i]); + } + mb->mv_type = MV_TYPE_8X8; + } + for (i = 0; i < 6; i++) + { + if (decode_inter_block(p, &mb->block[i], escape_type, cbp & 32) != 0) return -1; + cbp += cbp; + } + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int decode_I_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) +{ + int dquant; + int cbpc = get_intra_MCBPC(p); + if (cbpc < 0) + { + printf("intra_MCBPC error\n"); + return -1; + } + dquant = cbpc & 4; + decode_intra_mb_internal(p, mb, escape_type, qscale, cbpc, dquant); + if (show_bits(p, 16) == 0) + { +// printf("slice end???\n"); + } + return 0; +} + +int decode_P_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) +{ + int cbpc = get_inter_MCBPC(p); + if (cbpc == -1) + { + printf("inter_MCBPC error\n"); + return -1; + } + if (cbpc == -2) + { + mb->skip = 1; + } + else if (cbpc >= 0) + { + int dquant = cbpc & 8; + mb->skip = 0; + if ((cbpc & 4) != 0) + { + mb->intra = 1; + decode_intra_mb_internal(p, mb, escape_type, qscale, cbpc, dquant); + } + else + { + mb->intra = 0; + decode_inter_mb_internal(p, mb, escape_type, qscale, cbpc, dquant); + } + } + if (show_bits(p, 16) == 0) + { +// printf("slice end???\n"); + } + return 0; +} + +int decode_picture_header(BR *p, PICTURE *picture) +{ + int tmp, width = 0, height = 0; + if (get_bits(p, 17) != 1) + { + fprintf(stderr, "start code error\n"); + return -1; + } + tmp = get_bits(p, 5); + if (tmp != 0 && tmp != 1) + { + fprintf(stderr, "picture format error\n"); + return -1; + } + picture->escape_type = tmp; + picture->frame_number = get_bits(p, 8); +// printf("picture_format: %d\n", tmp); +// printf("picture_number: %d\n", get_bits(p, 8)); + tmp = get_bits(p, 3); + switch (tmp) + { + case 0: + width = get_bits(p, 8); + height = get_bits(p, 8); + break; + case 1: + width = get_bits(p, 16); + height = get_bits(p, 16); + break; + case 2: + width = 352, height = 288; + break; + case 3: + width = 176, height = 144; + break; + case 4: + width = 128, height = 96; + break; + case 5: + width = 320, height = 240; + break; + case 6: + width = 160, height = 120; + break; + default: + fprintf(stderr, "size error\n"); + return -1; + } + picture->width = width; + picture->height = height; +// printf("width: %d height: %d\n", width, height); + picture->picture_type = get_bits(p, 2); +// printf("picture_type: %d\n", tmp); + tmp = get_bits(p, 1); +// printf("deblocking flag: %d\n", tmp); + tmp = get_bits(p, 5); + picture->qscale = tmp; +// printf("qscale: %d\n", tmp); + // PEI + while (get_bits(p, 1) != 0) + { + flash_bits(p, 8); + } +// dump_marker(0, "dd header end"); + return 0; +} diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4v.h b/libeplayer3-arm/external/flv2mpeg4/src/m4v.h new file mode 100644 index 0000000..df5fd2e --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4v.h @@ -0,0 +1,139 @@ +/* + * MPEG4 structs and tables + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef M4V_H +#define M4V_H + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include "bitreader.h" +#include "dcprediction.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define VOS_STARTCODE 0x1B0 +#define USERDATA_STARTCODE 0x1B2 +#define GOP_STARTCODE 0x1B3 +#define VISUAL_OBJECT_STARTCODE 0x1B5 +#define VOP_STARTCODE 0x1B6 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _M4V_BLOCK +{ + int block[64]; + + int index; + int last_index; + +} M4V_BLOCK; + +typedef struct _M4V_MICROBLOCK +{ + M4V_BLOCK block[6]; + int qscale; + int dquant; // for encoding + + int ac_pred; + + int intra; + int skip; +#define MV_TYPE_16X16 0 +#define MV_TYPE_8X8 1 + int mv_type; + VLCDEC mv_x[4]; + VLCDEC mv_y[4]; + +} M4V_MICROBLOCK; + +typedef struct _M4V_VOL +{ + int width; + int height; + int time_bits; + + M4V_DCPRED dcpred; + +} M4V_VOL; + +typedef struct _M4V_VOP +{ +#define M4V_I_TYPE 0 +#define M4V_P_TYPE 1 +#define M4V_B_TYPE 2 + int picture_type; + int time; + int icount; + + int intra_dc_threshold; + + int rounding_type; + + int qscale; + int f_code; + int b_code; + +} M4V_VOP; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// same as FLV +static const uint8 zig_zag_scan[64] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +// M4V ADDED +static const uint8 alternate_horizontal_scan[64] = +{ + 0, 1, 2, 3, 8, 9, 16, 17, + 10, 11, 4, 5, 6, 7, 15, 14, + 13, 12, 19, 18, 24, 25, 32, 33, + 26, 27, 20, 21, 22, 23, 28, 29, + 30, 31, 34, 35, 40, 41, 48, 49, + 42, 43, 36, 37, 38, 39, 44, 45, + 46, 47, 50, 51, 56, 57, 58, 59, + 52, 53, 54, 55, 60, 61, 62, 63, +}; + +// M4V ADDED +static const uint8 alternate_vertical_scan[64] = +{ + 0, 8, 16, 24, 1, 9, 2, 10, + 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, + 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, + 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63, +}; + + +#endif // M4V_H + diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c new file mode 100644 index 0000000..8858741 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c @@ -0,0 +1,603 @@ +/* + * MPEG4 Bitstream/VLC Encoder + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "m4vencode.h" +#include "m4vencode_tables.h" +#include "bitwriter.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// same as H.263 +static const uint32 vlce_intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 }; +static const uint32 vlce_intra_MCBPC_bits[9] = { 1, 3, 3, 3, 4, 6, 6, 6, 9 }; +static const uint32 vlce_cbpy_code[16] = { 3, 5, 4, 9, 3, 7, 2, 11, 2, 3, 5, 10, 4, 8, 6, 3}; +static const uint32 vlce_cbpy_bits[16] = { 4, 5, 5, 4, 5, 4, 6, 4, 5, 6, 4, 4, 4, 4, 4, 2}; + +// same as H.263 +static const uint32 vlce_inter_MCBPC_code[28] = +{ + 1, 3, 2, 5, + 3, 4, 3, 3, + 3, 7, 6, 5, + 4, 4, 3, 2, + 2, 5, 4, 5, + 1, 0, 0, 0, /* Stuffing */ + 2, 12, 14, 15, +}; + +// same as H.263 +static const uint32 vlce_inter_MCBPC_bits[28] = +{ + 1, 4, 4, 6, /* inter */ + 5, 8, 8, 7, /* intra */ + 3, 7, 7, 9, /* interQ */ + 6, 9, 9, 9, /* intraQ */ + 3, 7, 7, 8, /* inter4 */ + 9, 0, 0, 0, /* Stuffing */ + 11, 13, 13, 13,/* inter4Q*/ +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void __inline encode_DC(BW *p, int level, int n) +{ + if (level < -255 || level > 255) printf("dc overflow\n"); +#if 1 + level += 256; + if (n < 4) + { + put_bits(p, uni_DCtab_lum_len[level], uni_DCtab_lum_bits[level]); + } + else + { + put_bits(p, uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level]); + } +#else + int size, v; + /* find number of bits */ + size = 0; + v = abs(level); + while (v) + { + v >>= 1; + size++; + } + if (n < 4) + { + /* luminance */ + put_bits(p, DCtab_lum[size][1], DCtab_lum[size][0]); + } + else + { + /* chrominance */ + put_bits(p, DCtab_chrom[size][1], DCtab_chrom[size][0]); + } + /* encode remaining bits */ + if (size > 0) + { + if (level < 0) + level = (-level) ^ ((1 << size) - 1); + put_bits(p, size, level); + if (size > 8) + put_bits(p, 1, 1); + } +#endif +} + +static void __inline encode_escape_3(BW *p, int last, int run, int level) +{ +#if 0 + put_bits(p, + 7 + 2 + 1 + 6 + 1 + 12 + 1, //30bit + (3 << 23) + (3 << 21) + (last << 20) + (run << 14) + (1 << 13) + (((level - 64) & 0xfff) << 1) + 1); +#else + put_bits(p, 7, 3); // escape + put_bits(p, 2, 3); // escape3 + put_bits(p, 1, last); + put_bits(p, 6, run); + put_bits(p, 1, 1); // marker + put_bits(p, 12, ((level - 64) & 0xfff)); + put_bits(p, 1, 1); // marker +#endif +} + +#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last)*128*64 + (run)*128 + (level)) + +static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) +{ + int i = intra; + int last_index = block->last_index; + int last_non_zero = i - 1; + const uint8 *scan_table = zig_zag_scan; // !!! +#if 1 + const uint8 *len_tab; + const uint32 *bits_tab; + if (intra) + { + len_tab = uni_mpeg4_intra_rl_len; + bits_tab = uni_mpeg4_intra_rl_bits; + } + else + { + len_tab = uni_mpeg4_inter_rl_len; + bits_tab = uni_mpeg4_inter_rl_bits; + } + for (; i < last_index; i++) + { + int level = block->block[scan_table[i]]; + if (level) + { + int run = i - last_non_zero - 1; + level += 64; + if ((level & (~127)) == 0) + { + const int index = UNI_MPEG4_ENC_INDEX(0, run, level); + put_bits(p, len_tab[index], bits_tab[index]); + } + else + { + encode_escape_3(p, 0, run, level); + } + last_non_zero = i; + } + } + { + int level = block->block[scan_table[i]]; + int run = i - last_non_zero - 1; + level += 64; + if ((level & (~127)) == 0) + { + const int index = UNI_MPEG4_ENC_INDEX(1, run, level); + put_bits(p, len_tab[index], bits_tab[index]); + } + else + { + encode_escape_3(p, 1, run, level); + } + } +#else + const RL *rl; + int last, sign, code; + if (intra) + { + rl = &rl_intra; + } + else + { + rl = &rl_inter; + } + for (; i <= last_index; i++) + { + const int slevel = block->block[scan_table[i]]; + if (slevel) + { + int level; + int run = i - last_non_zero - 1; + last = (i == last_index); + sign = 0; + level = slevel; + if (level < 0) + { + sign = 1; + level = -level; + } + code = get_rl_index(rl, last, run, level); + put_bits(p, rl->table_vlc[code][1], rl->table_vlc[code][0]); + if (code == rl->n) + { + int level1, run1; + level1 = level - rl->max_level[run][last]; + if (level1 < 1) + goto esc2; + code = get_rl_index(rl, last, run, level1); + if (code == rl->n) + { +esc2: + put_bits(p, 1, 1); + if (level > 64) + goto esc3; + run1 = run - rl->max_run[level][last] - 1; + if (run1 < 0) + goto esc3; + code = get_rl_index(rl, last, run1, level); + if (code == rl->n) + { +esc3: + /* third escape */ + put_bits(p, 1, 1); + put_bits(p, 1, last); + put_bits(p, 6, run); + put_bits(p, 1, 1); + put_bits(p, 12, slevel & 0xfff); + put_bits(p, 1, 1); + } + else + { + /* second escape */ + put_bits(p, 1, 0); + put_bits(p, rl->table_vlc[code][1], rl->table_vlc[code][0]); + put_bits(p, 1, sign); + } + } + else + { + /* first escape */ + put_bits(p, 1, 0); + put_bits(p, rl->table_vlc[code][1], rl->table_vlc[code][0]); + put_bits(p, 1, sign); + } + } + else + { + put_bits(p, 1, sign); + } + last_non_zero = i; + } + } +#endif +} + +static void __inline encode_intra_block(BW *bw, M4V_BLOCK *block, int n) +{ + encode_DC(bw, block->block[0], n); + encode_AC(bw, block, 1); +} + +static void __inline encode_inter_block(BW *bw, M4V_BLOCK *block) +{ + encode_AC(bw, block, 0); +} + +// same as H.263 +static void __inline encode_intra_I_MCBPC(BW *bw, int cbpc) +{ + put_bits(bw, vlce_intra_MCBPC_bits[cbpc], vlce_intra_MCBPC_code[cbpc]); +} + +// same as H.263 +static void __inline encode_intra_P_MCBPC(BW *bw, int cbpc) +{ + put_bits(bw, vlce_inter_MCBPC_bits[cbpc + 4], vlce_inter_MCBPC_code[cbpc + 4]); +} + +// same as H.263 +static void __inline encode_inter_16x16_MCBPC(BW *bw, int cbpc) +{ + put_bits(bw, vlce_inter_MCBPC_bits[cbpc], vlce_inter_MCBPC_code[cbpc]); +} + +// same as H.263 +static void __inline encode_inter_8x8_MCBPC(BW *bw, int cbpc) +{ + put_bits(bw, vlce_inter_MCBPC_bits[cbpc + 16], vlce_inter_MCBPC_code[cbpc + 16]); +} + + +// same as H.263 +static void __inline encode_cbpy(BW *bw, int cbpy) +{ + put_bits(bw, vlce_cbpy_bits[cbpy], vlce_cbpy_code[cbpy]); +} + +// same as H.263 +static void __inline encode_dquant(BW *bw, int dquant) +{ + const uint32 dquant_code[5] = {1, 0, -1, 2, 3}; + if (dquant) + { + put_bits(bw, 2, dquant_code[dquant + 2]); + } +} + +// same as FLV +static void __inline encode_motion(BW *bw, VLCDEC *mv_x, VLCDEC *mv_y) +{ + put_vlcdec(bw, mv_x); + if (mv_x->bits_ex) + { + put_bits(bw, 1, mv_x->value_ex & 1); + if (mv_x->bits_ex > 1) + { + put_bits(bw, mv_x->bits_ex - 1, mv_x->value_ex >> 1); + } + } + put_vlcdec(bw, mv_y); + if (mv_y->bits_ex) + { + put_bits(bw, 1, mv_y->value_ex & 1); + if (mv_y->bits_ex > 1) + { + put_bits(bw, mv_y->bits_ex - 1, mv_y->value_ex >> 1); + } + } +} + +// same as FLV +static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb) +{ + int cbp = 0, cbpc, cbpy; + int i; + for (i = 0; i < 6; i++) + { + if (mb->block[i].last_index >= 0) + { + cbp |= 1 << (5 - i); + } + } + cbpc = cbp & 3; + cbpy = cbp >> 2; + cbpy ^= 0xF; + if (mb->dquant) cbpc += 8; + switch (mb->mv_type) + { + case MV_TYPE_16X16: + encode_inter_16x16_MCBPC(bw, cbpc); + encode_cbpy(bw, cbpy); + encode_dquant(bw, mb->dquant); + encode_motion(bw, &mb->mv_x[0], &mb->mv_y[0]); + break; + case MV_TYPE_8X8: + encode_inter_8x8_MCBPC(bw, cbpc); + encode_cbpy(bw, cbpy); + encode_dquant(bw, mb->dquant); + for (i = 0; i < 4; i++) + { + encode_motion(bw, &mb->mv_x[i], &mb->mv_y[i]); + } + break; + } + for (i = 0; i < 6; i++) + { + encode_inter_block(bw, &mb->block[i]); + } +} + +static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int iframe) +{ + int cbp = 0, cbpc, cbpy; + int i; + for (i = 0; i < 6; i++) + { + if (mb->block[i].last_index >= 1) + { + cbp |= 1 << (5 - i); + } + } + cbpc = cbp & 3; + if (iframe) + { + if (mb->dquant) cbpc += 4; + encode_intra_I_MCBPC(bw, cbpc); + } + else + { + if (mb->dquant) cbpc += 8; + encode_intra_P_MCBPC(bw, cbpc); + } + put_bits(bw, 1, 0); // AC Prediction = no + cbpy = cbp >> 2; + encode_cbpy(bw, cbpy); + encode_dquant(bw, mb->dquant); + for (i = 0; i < 6; i++) + { + encode_intra_block(bw, &mb->block[i], i); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static int __inline encode_vo_header(BW *p) +{ + put_bits(p, 16, 0); + put_bits(p, 16, VOS_STARTCODE); + put_bits(p, 8, 1); // *** profile_and_level_indidation + put_bits(p, 16, 0); + put_bits(p, 16, VISUAL_OBJECT_STARTCODE); + put_bits(p, 1, 1); + put_bits(p, 4, 1); // vo_vel_id + put_bits(p, 3, 1); // priority + put_bits(p, 4, 1); // visual_object_type = video object + put_bits(p, 1, 0); // video signal type = no clue + m4v_stuffing(p); + return 0; +} + +static int __inline encode_vol_header(BW *p, M4V_VOL *vol) +{ + const int vo_number = 0; + const int vol_number = 0; + put_bits(p, 16, 0); + put_bits(p, 16, 0x100 + vo_number); + put_bits(p, 16, 0); + put_bits(p, 16, 0x120 + vol_number); + put_bits(p, 1, 0); // random_accessible_vol + put_bits(p, 8, 1); // video_object_type_indication = Simple Object Type + put_bits(p, 1, 0); //is_object_layer_identifier + put_bits(p, 4, 1); // *** aspect_ratio_info = 1(1:1) + put_bits(p, 1, 0); //vol_control_parameters + put_bits(p, 2, 0); // shape_type + put_bits(p, 1, 1); // marker + if (vol->time_bits != 5) return -1; // for vop_time_increment_resolution = 30 + put_bits(p, 16, 30); // *** vop_time_increment_resolution = 30 + put_bits(p, 1, 1); // marker + put_bits(p, 1, 0); // fixed vop rate = no + put_bits(p, 1, 1); // marker + put_bits(p, 13, vol->width); // width + put_bits(p, 1, 1); // marker + put_bits(p, 13, vol->height); // height + put_bits(p, 1, 1); // marker + put_bits(p, 1, 0); // progressive = false + put_bits(p, 1, 1); // obmc disable = true + put_bits(p, 1, 0); // sprite = disable + put_bits(p, 1, 0); // not8bit = false + put_bits(p, 1, 0); // quant type = H.263 + put_bits(p, 1, 1); // complexity estimaition disable = true + put_bits(p, 1, 1); // resync marker disable = true + put_bits(p, 1, 0); // data pertitioning = false + put_bits(p, 1, 0); // scalability = false + m4v_stuffing(p); + return 0; +} + +static int __inline encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vop_not_coded) +{ +// static int time_old = 0; + int time_incr = vop->icount; + if (vop->time != 0) + time_incr = 0; + put_bits(p, 16, 0); + put_bits(p, 16, VOP_STARTCODE); + put_bits(p, 2, vop->picture_type); +// printf("not_code:%d vop_time: %d\n", vop_not_coded, vop->time); +// printf("pic:%d icount:%d vop_time: %d\n", vop->picture_type, time_incr, vop->time); + /* if (time_old > vop->time) + { + put_bits(p, 1, 1); + } + + time_old = vop->time; + */ + // !!!!! + while (time_incr--) + put_bits(p, 1, 1); + put_bits(p, 1, 0); + put_bits(p, 1, 1); // marker + put_bits(p, time_bits, vop->time); // time_increment + put_bits(p, 1, 1); // marker + if (vop_not_coded) + { + put_bits(p, 1, 0); // vop coded + return 0; + } + put_bits(p, 1, 1); // vop coded + if (vop->picture_type == M4V_P_TYPE) + { + put_bits(p, 1, vop->rounding_type); // rounding type + } + put_bits(p, 3, 0); // intra dc VLC threashold + put_bits(p, 5, vop->qscale); // qscale + if (vop->picture_type != M4V_I_TYPE) + { + put_bits(p, 3, vop->f_code); + } + if (vop->picture_type == M4V_B_TYPE) + { + put_bits(p, 3, vop->b_code); + } + return 0; +} + +static __inline int encode_gop_header(BW *bw, uint32 time_ms) +{ + int sec, min, hour; + sec = time_ms / 1000; + min = sec / 60; + sec %= 60; + hour = min / 60; + min %= 60; + hour %= 24; + put_bits(bw, 16, 0); + put_bits(bw, 16, GOP_STARTCODE); + put_bits(bw, 5, hour); + put_bits(bw, 6, min); + put_bits(bw, 1, 1); + put_bits(bw, 6, sec); + put_bits(bw, 1, 0); // closed_gop == NO + put_bits(bw, 1, 0); // broken link == NO + printf("GOP %02d:%02d:%02d\n", hour, min, sec); + m4v_stuffing(bw); + return 0; +} + +static int __inline encode_user_header(BW *p) +{ + put_bits(p, 16, 0); + put_bits(p, 16, USERDATA_STARTCODE); + put_bits(p, 8, 'v'); + put_bits(p, 8, 'i'); + put_bits(p, 8, 'x'); + put_bits(p, 8, 'y'); + put_bits(p, 8, '.'); + put_bits(p, 8, 'n'); + put_bits(p, 8, 'e'); + put_bits(p, 8, 't'); + m4v_stuffing(p); + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void m4v_encode_m4v_header(BW *bw, M4V_VOL *vol, uint32 time) +{ + encode_vo_header(bw); + encode_vol_header(bw, vol); +// encode_gop_header(bw, time); + encode_user_header(bw); +} + +void m4v_encode_vop_header(BW *bw, M4V_VOP *vop, int time_bits, int vop_not_coded) +{ + encode_vop_header(bw, vop, time_bits, vop_not_coded); +} + +void m4v_encode_I_mb(BW *bw, M4V_MICROBLOCK *mb) +{ + encode_mb_intra_internal(bw, mb, 1); +} + +// same as FLV +void m4v_encode_P_mb(BW *bw, M4V_MICROBLOCK *mb) +{ + if (mb->skip) + { + put_bits(bw, 1, 1); // not coded + return; + } + else + { + put_bits(bw, 1, 0); // coded + } + if (mb->intra) + { + encode_mb_intra_internal(bw, mb, 0); + } + else + { + encode_mb_inter_internal(bw, mb); + } +} + +int m4v_encode_I_dcpred(M4V_MICROBLOCK *mb, M4V_DCPRED *dcpred, int mb_x, int mb_y) +{ + int n; + if (mb->intra) + { + dcpred_set_qscale(dcpred, mb->qscale); + dcpred_set_pos(dcpred, mb_x, mb_y); + for (n = 0; n < 6; n ++) + { + int level = dcpred_for_enc(dcpred, n, mb->block[n].block[0]); + mb->block[n].block[0] = level; + } + } + return 0; +} diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.h b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.h new file mode 100644 index 0000000..f462ce1 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.h @@ -0,0 +1,37 @@ +/* + * MPEG4 Bitstream/VLC Encoder + * + * Copyright (c) 2006 vixy project + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef M4VENCODE_H +#define M4VENCODE_H + +#include "m4v.h" +#include "bitwriter.h" + +void m4v_encode_m4v_header(BW *bw, M4V_VOL *vol, uint32 time); +void m4v_encode_vop_header(BW *bw, M4V_VOP *vop, int time_bits, int vop_not_coded); + +void m4v_encode_I_mb(BW *bw, M4V_MICROBLOCK *mb); +void m4v_encode_P_mb(BW *bw, M4V_MICROBLOCK *mb); + +int m4v_encode_I_dcpred(M4V_MICROBLOCK *mb, M4V_DCPRED *dcpred, int mb_x, int mb_y); + +#endif // M4VENCODE_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4vencode_tables.h b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode_tables.h new file mode 100644 index 0000000..3c1c23b --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode_tables.h @@ -0,0 +1,3993 @@ +/* + * MPEG4 Bitstream/VLC tables + * + * Copyright (c) 2006 vixy project + * + * This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/) + * See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef M4VENCODE_TABLES_H +#define M4VENCODE_TABLES_H + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static const uint32 uni_DCtab_lum_bits[] = +{ + 1535, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, 8, 9, 6, 3, 7, 10, 11, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, +}; + +static const uint32 uni_DCtab_lum_len[] = +{ + 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 4, 4, 3, 3, 3, 4, 4, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 +}; + +static const uint32 uni_DCtab_chrom_bits[] = +{ + 1535, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 4, 5, 4, 3, 5, 6, 7, 12, + 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511 +}; + +static const uint32 uni_DCtab_chrom_len[] = +{ + 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 4, 4, 3, 2, 3, 4, 4, 6, + 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static const uint32 uni_mpeg4_intra_rl_bits[] = +{ + 31473537, 31473539, 31473541, 31473543, 31473545, 31473547, 31473549, 31473551, 31473553, 31473555, 49317, 49315, 49313, 24643, 24641, 24589, + 24591, 12317, 12319, 12353, 12355, 6211, 6215, 6217, 6219, 3131, 3133, 3135, 1583, 805, 807, + 811, 409, 411, 223, 109, 53, 165, 163, 161, 67, 65, 13, 15, 29, 31, + 65, 67, 67, 71, 73, 75, 59, 61, 63, 47, 37, 39, 43, 25, 27, + 31, 13, 5, 0, 4, 12, 30, 26, 24, 42, 38, 36, 46, 62, 60, + 58, 74, 72, 70, 66, 66, 64, 30, 28, 14, 12, 64, 66, 160, 162, + 164, 52, 108, 222, 410, 408, 810, 806, 804, 1582, 3134, 3132, 3130, 6218, 6216, + 6214, 6210, 12354, 12352, 12318, 12316, 24590, 24588, 24640, 24642, 49312, 49314, 49316, 31465583, 31465585, + 31465587, 31465589, 31465591, 31465593, 31465595, 31465597, 31465599, 31489921, 31489923, 31489925, 31489927, 31489929, 31489931, 31489933, 31489935, + 31489937, 31489939, 31489941, 31489943, 31489945, 31489947, 31489949, 31489951, 31489953, 31489955, 31489957, 31489959, 31489961, 31489963, 31489965, + 31489967, 31489969, 31489971, 31489973, 31489975, 31489977, 31489979, 31489981, 31489983, 31489985, 31489987, 31489989, 31489991, 31489993, 114853, + 114851, 114849, 57411, 57409, 57357, 57359, 28701, 28703, 24645, 12315, 6207, 6209, 3129, 1581, 809, + 221, 171, 167, 69, 27, 63, 65, 57, 45, 41, 29, 0, 28, 40, 44, + 56, 64, 62, 26, 68, 166, 170, 220, 808, 1580, 3128, 6208, 6206, 12314, 24644, + 28702, 28700, 57358, 57356, 57408, 57410, 114848, 114850, 114852, 31481913, 31481915, 31481917, 31481919, 31481921, 31481923, + 31481925, 31481927, 31481929, 31481931, 31481933, 31481935, 31481937, 31481939, 31481941, 31481943, 31481945, 31481947, 31481949, 31481951, 31481953, + 31481955, 31481957, 31481959, 31481961, 31481963, 31481965, 31481967, 31481969, 31481971, 31481973, 31481975, 31481977, 31481979, 31481981, 31481983, + 31506305, 31506307, 31506309, 31506311, 31506313, 31506315, 31506317, 31506319, 31506321, 31506323, 31506325, 31506327, 31506329, 31506331, 31506333, + 31506335, 31506337, 31506339, 31506341, 31506343, 31506345, 31506347, 31506349, 31506351, 31506353, 31506355, 31506357, 31506359, 31506361, 31506363, + 31506365, 31506367, 31506369, 31506371, 31506373, 31506375, 31506377, 31506379, 31506381, 31506383, 31506385, 31506387, 31506389, 31506391, 31506393, + 31506395, 31506397, 31506399, 31506401, 31506403, 31506405, 31506407, 31506409, 31506411, 7231, 3631, 1829, 1579, 407, 173, + 25, 61, 43, 23, 0, 22, 42, 60, 24, 172, 406, 1578, 1828, 3630, 7230, + 31498263, 31498265, 31498267, 31498269, 31498271, 31498273, 31498275, 31498277, 31498279, 31498281, 31498283, 31498285, 31498287, 31498289, 31498291, + 31498293, 31498295, 31498297, 31498299, 31498301, 31498303, 31498305, 31498307, 31498309, 31498311, 31498313, 31498315, 31498317, 31498319, 31498321, + 31498323, 31498325, 31498327, 31498329, 31498331, 31498333, 31498335, 31498337, 31498339, 31498341, 31498343, 31498345, 31498347, 31498349, 31498351, + 31498353, 31498355, 31498357, 31498359, 31498361, 31498363, 31498365, 31498367, 31522689, 31522691, 31522693, 31522695, 31522697, 31522699, 31522701, + 31522703, 31522705, 31522707, 31522709, 31522711, 31522713, 31522715, 31522717, 31522719, 31522721, 31522723, 31522725, 31522727, 31522729, 31522731, + 31522733, 31522735, 31522737, 31522739, 31522741, 31522743, 31522745, 31522747, 31522749, 31522751, 31522753, 31522755, 31522757, 31522759, 31522761, + 31522763, 31522765, 31522767, 31522769, 31522771, 31522773, 31522775, 31522777, 31522779, 31522781, 31522783, 31522785, 31522787, 31522789, 31522791, + 31522793, 31522795, 114859, 114855, 12311, 6203, 3127, 803, 23, 59, 55, 35, 0, 34, 54, + 58, 22, 802, 3126, 6202, 12310, 114854, 114858, 31514647, 31514649, 31514651, 31514653, 31514655, 31514657, 31514659, + 31514661, 31514663, 31514665, 31514667, 31514669, 31514671, 31514673, 31514675, 31514677, 31514679, 31514681, 31514683, 31514685, 31514687, 31514689, + 31514691, 31514693, 31514695, 31514697, 31514699, 31514701, 31514703, 31514705, 31514707, 31514709, 31514711, 31514713, 31514715, 31514717, 31514719, + 31514721, 31514723, 31514725, 31514727, 31514729, 31514731, 31514733, 31514735, 31514737, 31514739, 31514741, 31514743, 31514745, 31514747, 31514749, + 31514751, 31539073, 31539075, 31539077, 31539079, 31539081, 31539083, 31539085, 31539087, 31539089, 31539091, 31539093, 31539095, 31539097, 31539099, + 31539101, 31539103, 31539105, 31539107, 31539109, 31539111, 31539113, 31539115, 31539117, 31539119, 31539121, 31539123, 31539125, 31539127, 31539129, + 31539131, 31539133, 31539135, 31539137, 31539139, 31539141, 31539143, 31539145, 31539147, 31539149, 31539151, 31539153, 31539155, 31539157, 31539159, + 31539161, 31539163, 31539165, 31539167, 31539169, 31539171, 31539173, 31539175, 31539177, 31539179, 31539181, 31539183, 31539185, 31539187, 12309, + 6213, 801, 21, 69, 33, 0, 32, 68, 20, 800, 6212, 12308, 31531023, 31531025, 31531027, + 31531029, 31531031, 31531033, 31531035, 31531037, 31531039, 31531041, 31531043, 31531045, 31531047, 31531049, 31531051, 31531053, 31531055, 31531057, + 31531059, 31531061, 31531063, 31531065, 31531067, 31531069, 31531071, 31531073, 31531075, 31531077, 31531079, 31531081, 31531083, 31531085, 31531087, + 31531089, 31531091, 31531093, 31531095, 31531097, 31531099, 31531101, 31531103, 31531105, 31531107, 31531109, 31531111, 31531113, 31531115, 31531117, + 31531119, 31531121, 31531123, 31531125, 31531127, 31531129, 31531131, 31531133, 31531135, 31555457, 31555459, 31555461, 31555463, 31555465, 31555467, + 31555469, 31555471, 31555473, 31555475, 31555477, 31555479, 31555481, 31555483, 31555485, 31555487, 31555489, 31555491, 31555493, 31555495, 31555497, + 31555499, 31555501, 31555503, 31555505, 31555507, 31555509, 31555511, 31555513, 31555515, 31555517, 31555519, 31555521, 31555523, 31555525, 31555527, + 31555529, 31555531, 31555533, 31555535, 31555537, 31555539, 31555541, 31555543, 31555545, 31555547, 31555549, 31555551, 31555553, 31555555, 31555557, + 31555559, 31555561, 31555563, 31555565, 31555567, 31555569, 31555571, 12305, 6201, 795, 17, 57, 27, 0, 26, + 56, 16, 794, 6200, 12304, 31547407, 31547409, 31547411, 31547413, 31547415, 31547417, 31547419, 31547421, 31547423, 31547425, + 31547427, 31547429, 31547431, 31547433, 31547435, 31547437, 31547439, 31547441, 31547443, 31547445, 31547447, 31547449, 31547451, 31547453, 31547455, + 31547457, 31547459, 31547461, 31547463, 31547465, 31547467, 31547469, 31547471, 31547473, 31547475, 31547477, 31547479, 31547481, 31547483, 31547485, + 31547487, 31547489, 31547491, 31547493, 31547495, 31547497, 31547499, 31547501, 31547503, 31547505, 31547507, 31547509, 31547511, 31547513, 31547515, + 31547517, 31547519, 31571841, 31571843, 31571845, 31571847, 31571849, 31571851, 31571853, 31571855, 31571857, 31571859, 31571861, 31571863, 31571865, + 31571867, 31571869, 31571871, 31571873, 31571875, 31571877, 31571879, 31571881, 31571883, 31571885, 31571887, 31571889, 31571891, 31571893, 31571895, + 31571897, 31571899, 31571901, 31571903, 31571905, 31571907, 31571909, 31571911, 31571913, 31571915, 31571917, 31571919, 31571921, 31571923, 31571925, + 31571927, 31571929, 31571931, 31571933, 31571935, 31571937, 31571939, 31571941, 31571943, 31571945, 31571947, 31571949, 31571951, 31571953, 31571955, + 49321, 6199, 1573, 169, 55, 37, 0, 36, 54, 168, 1572, 6198, 49320, 31563791, 31563793, + 31563795, 31563797, 31563799, 31563801, 31563803, 31563805, 31563807, 31563809, 31563811, 31563813, 31563815, 31563817, 31563819, 31563821, 31563823, + 31563825, 31563827, 31563829, 31563831, 31563833, 31563835, 31563837, 31563839, 31563841, 31563843, 31563845, 31563847, 31563849, 31563851, 31563853, + 31563855, 31563857, 31563859, 31563861, 31563863, 31563865, 31563867, 31563869, 31563871, 31563873, 31563875, 31563877, 31563879, 31563881, 31563883, + 31563885, 31563887, 31563889, 31563891, 31563893, 31563895, 31563897, 31563899, 31563901, 31563903, 31588225, 31588227, 31588229, 31588231, 31588233, + 31588235, 31588237, 31588239, 31588241, 31588243, 31588245, 31588247, 31588249, 31588251, 31588253, 31588255, 31588257, 31588259, 31588261, 31588263, + 31588265, 31588267, 31588269, 31588271, 31588273, 31588275, 31588277, 31588279, 31588281, 31588283, 31588285, 31588287, 31588289, 31588291, 31588293, + 31588295, 31588297, 31588299, 31588301, 31588303, 31588305, 31588307, 31588309, 31588311, 31588313, 31588315, 31588317, 31588319, 31588321, 31588323, + 31588325, 31588327, 31588329, 31588331, 31588333, 31588335, 31588337, 31588339, 49327, 6197, 1577, 175, 53, 41, 0, + 40, 52, 174, 1576, 6196, 49326, 31580175, 31580177, 31580179, 31580181, 31580183, 31580185, 31580187, 31580189, 31580191, + 31580193, 31580195, 31580197, 31580199, 31580201, 31580203, 31580205, 31580207, 31580209, 31580211, 31580213, 31580215, 31580217, 31580219, 31580221, + 31580223, 31580225, 31580227, 31580229, 31580231, 31580233, 31580235, 31580237, 31580239, 31580241, 31580243, 31580245, 31580247, 31580249, 31580251, + 31580253, 31580255, 31580257, 31580259, 31580261, 31580263, 31580265, 31580267, 31580269, 31580271, 31580273, 31580275, 31580277, 31580279, 31580281, + 31580283, 31580285, 31580287, 31604609, 31604611, 31604613, 31604615, 31604617, 31604619, 31604621, 31604623, 31604625, 31604627, 31604629, 31604631, + 31604633, 31604635, 31604637, 31604639, 31604641, 31604643, 31604645, 31604647, 31604649, 31604651, 31604653, 31604655, 31604657, 31604659, 31604661, + 31604663, 31604665, 31604667, 31604669, 31604671, 31604673, 31604675, 31604677, 31604679, 31604681, 31604683, 31604685, 31604687, 31604689, 31604691, + 31604693, 31604695, 31604697, 31604699, 31604701, 31604703, 31604705, 31604707, 31604709, 31604711, 31604713, 31604715, 31604717, 31604719, 31604721, + 31604723, 31604725, 31604727, 12307, 479, 19, 51, 0, 50, 18, 478, 12306, 31596555, 31596557, 31596559, + 31596561, 31596563, 31596565, 31596567, 31596569, 31596571, 31596573, 31596575, 31596577, 31596579, 31596581, 31596583, 31596585, 31596587, 31596589, + 31596591, 31596593, 31596595, 31596597, 31596599, 31596601, 31596603, 31596605, 31596607, 31596609, 31596611, 31596613, 31596615, 31596617, 31596619, + 31596621, 31596623, 31596625, 31596627, 31596629, 31596631, 31596633, 31596635, 31596637, 31596639, 31596641, 31596643, 31596645, 31596647, 31596649, + 31596651, 31596653, 31596655, 31596657, 31596659, 31596661, 31596663, 31596665, 31596667, 31596669, 31596671, 31620993, 31620995, 31620997, 31620999, + 31621001, 31621003, 31621005, 31621007, 31621009, 31621011, 31621013, 31621015, 31621017, 31621019, 31621021, 31621023, 31621025, 31621027, 31621029, + 31621031, 31621033, 31621035, 31621037, 31621039, 31621041, 31621043, 31621045, 31621047, 31621049, 31621051, 31621053, 31621055, 31621057, 31621059, + 31621061, 31621063, 31621065, 31621067, 31621069, 31621071, 31621073, 31621075, 31621077, 31621079, 31621081, 31621083, 31621085, 31621087, 31621089, + 31621091, 31621093, 31621095, 31621097, 31621099, 31621101, 31621103, 31621105, 31621107, 31621109, 31621111, 24647, 3121, 71, 49, + 0, 48, 70, 3120, 24646, 31612939, 31612941, 31612943, 31612945, 31612947, 31612949, 31612951, 31612953, 31612955, 31612957, + 31612959, 31612961, 31612963, 31612965, 31612967, 31612969, 31612971, 31612973, 31612975, 31612977, 31612979, 31612981, 31612983, 31612985, 31612987, + 31612989, 31612991, 31612993, 31612995, 31612997, 31612999, 31613001, 31613003, 31613005, 31613007, 31613009, 31613011, 31613013, 31613015, 31613017, + 31613019, 31613021, 31613023, 31613025, 31613027, 31613029, 31613031, 31613033, 31613035, 31613037, 31613039, 31613041, 31613043, 31613045, 31613047, + 31613049, 31613051, 31613053, 31613055, 31637377, 31637379, 31637381, 31637383, 31637385, 31637387, 31637389, 31637391, 31637393, 31637395, 31637397, + 31637399, 31637401, 31637403, 31637405, 31637407, 31637409, 31637411, 31637413, 31637415, 31637417, 31637419, 31637421, 31637423, 31637425, 31637427, + 31637429, 31637431, 31637433, 31637435, 31637437, 31637439, 31637441, 31637443, 31637445, 31637447, 31637449, 31637451, 31637453, 31637455, 31637457, + 31637459, 31637461, 31637463, 31637465, 31637467, 31637469, 31637471, 31637473, 31637475, 31637477, 31637479, 31637481, 31637483, 31637485, 31637487, + 31637489, 31637491, 31637493, 31637495, 31637497, 14397, 237, 47, 0, 46, 236, 14396, 31629321, 31629323, 31629325, + 31629327, 31629329, 31629331, 31629333, 31629335, 31629337, 31629339, 31629341, 31629343, 31629345, 31629347, 31629349, 31629351, 31629353, 31629355, + 31629357, 31629359, 31629361, 31629363, 31629365, 31629367, 31629369, 31629371, 31629373, 31629375, 31629377, 31629379, 31629381, 31629383, 31629385, + 31629387, 31629389, 31629391, 31629393, 31629395, 31629397, 31629399, 31629401, 31629403, 31629405, 31629407, 31629409, 31629411, 31629413, 31629415, + 31629417, 31629419, 31629421, 31629423, 31629425, 31629427, 31629429, 31629431, 31629433, 31629435, 31629437, 31629439, 31653761, 31653763, 31653765, + 31653767, 31653769, 31653771, 31653773, 31653775, 31653777, 31653779, 31653781, 31653783, 31653785, 31653787, 31653789, 31653791, 31653793, 31653795, + 31653797, 31653799, 31653801, 31653803, 31653805, 31653807, 31653809, 31653811, 31653813, 31653815, 31653817, 31653819, 31653821, 31653823, 31653825, + 31653827, 31653829, 31653831, 31653833, 31653835, 31653837, 31653839, 31653841, 31653843, 31653845, 31653847, 31653849, 31653851, 31653853, 31653855, + 31653857, 31653859, 31653861, 31653863, 31653865, 31653867, 31653869, 31653871, 31653873, 31653875, 31653877, 31653879, 31653881, 14395, 1833, + 51, 0, 50, 1832, 14394, 31645705, 31645707, 31645709, 31645711, 31645713, 31645715, 31645717, 31645719, 31645721, 31645723, + 31645725, 31645727, 31645729, 31645731, 31645733, 31645735, 31645737, 31645739, 31645741, 31645743, 31645745, 31645747, 31645749, 31645751, 31645753, + 31645755, 31645757, 31645759, 31645761, 31645763, 31645765, 31645767, 31645769, 31645771, 31645773, 31645775, 31645777, 31645779, 31645781, 31645783, + 31645785, 31645787, 31645789, 31645791, 31645793, 31645795, 31645797, 31645799, 31645801, 31645803, 31645805, 31645807, 31645809, 31645811, 31645813, + 31645815, 31645817, 31645819, 31645821, 31645823, 31670145, 31670147, 31670149, 31670151, 31670153, 31670155, 31670157, 31670159, 31670161, 31670163, + 31670165, 31670167, 31670169, 31670171, 31670173, 31670175, 31670177, 31670179, 31670181, 31670183, 31670185, 31670187, 31670189, 31670191, 31670193, + 31670195, 31670197, 31670199, 31670201, 31670203, 31670205, 31670207, 31670209, 31670211, 31670213, 31670215, 31670217, 31670219, 31670221, 31670223, + 31670225, 31670227, 31670229, 31670231, 31670233, 31670235, 31670237, 31670239, 31670241, 31670243, 31670245, 31670247, 31670249, 31670251, 31670253, + 31670255, 31670257, 31670259, 31670261, 31670263, 31670265, 28693, 3627, 49, 0, 48, 3626, 28692, 31662089, 31662091, + 31662093, 31662095, 31662097, 31662099, 31662101, 31662103, 31662105, 31662107, 31662109, 31662111, 31662113, 31662115, 31662117, 31662119, 31662121, + 31662123, 31662125, 31662127, 31662129, 31662131, 31662133, 31662135, 31662137, 31662139, 31662141, 31662143, 31662145, 31662147, 31662149, 31662151, + 31662153, 31662155, 31662157, 31662159, 31662161, 31662163, 31662165, 31662167, 31662169, 31662171, 31662173, 31662175, 31662177, 31662179, 31662181, + 31662183, 31662185, 31662187, 31662189, 31662191, 31662193, 31662195, 31662197, 31662199, 31662201, 31662203, 31662205, 31662207, 31686529, 31686531, + 31686533, 31686535, 31686537, 31686539, 31686541, 31686543, 31686545, 31686547, 31686549, 31686551, 31686553, 31686555, 31686557, 31686559, 31686561, + 31686563, 31686565, 31686567, 31686569, 31686571, 31686573, 31686575, 31686577, 31686579, 31686581, 31686583, 31686585, 31686587, 31686589, 31686591, + 31686593, 31686595, 31686597, 31686599, 31686601, 31686603, 31686605, 31686607, 31686609, 31686611, 31686613, 31686615, 31686617, 31686619, 31686621, + 31686623, 31686625, 31686627, 31686629, 31686631, 31686633, 31686635, 31686637, 31686639, 31686641, 31686643, 31686645, 31686647, 31686649, 28689, + 7223, 15, 0, 14, 7222, 28688, 31678473, 31678475, 31678477, 31678479, 31678481, 31678483, 31678485, 31678487, 31678489, + 31678491, 31678493, 31678495, 31678497, 31678499, 31678501, 31678503, 31678505, 31678507, 31678509, 31678511, 31678513, 31678515, 31678517, 31678519, + 31678521, 31678523, 31678525, 31678527, 31678529, 31678531, 31678533, 31678535, 31678537, 31678539, 31678541, 31678543, 31678545, 31678547, 31678549, + 31678551, 31678553, 31678555, 31678557, 31678559, 31678561, 31678563, 31678565, 31678567, 31678569, 31678571, 31678573, 31678575, 31678577, 31678579, + 31678581, 31678583, 31678585, 31678587, 31678589, 31678591, 31702913, 31702915, 31702917, 31702919, 31702921, 31702923, 31702925, 31702927, 31702929, + 31702931, 31702933, 31702935, 31702937, 31702939, 31702941, 31702943, 31702945, 31702947, 31702949, 31702951, 31702953, 31702955, 31702957, 31702959, + 31702961, 31702963, 31702965, 31702967, 31702969, 31702971, 31702973, 31702975, 31702977, 31702979, 31702981, 31702983, 31702985, 31702987, 31702989, + 31702991, 31702993, 31702995, 31702997, 31702999, 31703001, 31703003, 31703005, 31703007, 31703009, 31703011, 31703013, 31703015, 31703017, 31703019, + 31703021, 31703023, 31703025, 31703027, 31703029, 31703031, 31703033, 114857, 14405, 177, 0, 176, 14404, 114856, 31694857, + 31694859, 31694861, 31694863, 31694865, 31694867, 31694869, 31694871, 31694873, 31694875, 31694877, 31694879, 31694881, 31694883, 31694885, 31694887, + 31694889, 31694891, 31694893, 31694895, 31694897, 31694899, 31694901, 31694903, 31694905, 31694907, 31694909, 31694911, 31694913, 31694915, 31694917, + 31694919, 31694921, 31694923, 31694925, 31694927, 31694929, 31694931, 31694933, 31694935, 31694937, 31694939, 31694941, 31694943, 31694945, 31694947, + 31694949, 31694951, 31694953, 31694955, 31694957, 31694959, 31694961, 31694963, 31694965, 31694967, 31694969, 31694971, 31694973, 31694975, 31719297, + 31719299, 31719301, 31719303, 31719305, 31719307, 31719309, 31719311, 31719313, 31719315, 31719317, 31719319, 31719321, 31719323, 31719325, 31719327, + 31719329, 31719331, 31719333, 31719335, 31719337, 31719339, 31719341, 31719343, 31719345, 31719347, 31719349, 31719351, 31719353, 31719355, 31719357, + 31719359, 31719361, 31719363, 31719365, 31719367, 31719369, 31719371, 31719373, 31719375, 31719377, 31719379, 31719381, 31719383, 31719385, 31719387, + 31719389, 31719391, 31719393, 31719395, 31719397, 31719399, 31719401, 31719403, 31719405, 31719407, 31719409, 31719411, 31719413, 31719415, 31719417, + 114863, 14393, 117, 0, 116, 14392, 114862, 31711241, 31711243, 31711245, 31711247, 31711249, 31711251, 31711253, 31711255, + 31711257, 31711259, 31711261, 31711263, 31711265, 31711267, 31711269, 31711271, 31711273, 31711275, 31711277, 31711279, 31711281, 31711283, 31711285, + 31711287, 31711289, 31711291, 31711293, 31711295, 31711297, 31711299, 31711301, 31711303, 31711305, 31711307, 31711309, 31711311, 31711313, 31711315, + 31711317, 31711319, 31711321, 31711323, 31711325, 31711327, 31711329, 31711331, 31711333, 31711335, 31711337, 31711339, 31711341, 31711343, 31711345, + 31711347, 31711349, 31711351, 31711353, 31711355, 31711357, 31711359, 31735681, 31735683, 31735685, 31735687, 31735689, 31735691, 31735693, 31735695, + 31735697, 31735699, 31735701, 31735703, 31735705, 31735707, 31735709, 31735711, 31735713, 31735715, 31735717, 31735719, 31735721, 31735723, 31735725, + 31735727, 31735729, 31735731, 31735733, 31735735, 31735737, 31735739, 31735741, 31735743, 31735745, 31735747, 31735749, 31735751, 31735753, 31735755, + 31735757, 31735759, 31735761, 31735763, 31735765, 31735767, 31735769, 31735771, 31735773, 31735775, 31735777, 31735779, 31735781, 31735783, 31735785, + 31735787, 31735789, 31735791, 31735793, 31735795, 31735797, 31735799, 31735801, 31735803, 14391, 477, 0, 476, 14390, 31727623, + 31727625, 31727627, 31727629, 31727631, 31727633, 31727635, 31727637, 31727639, 31727641, 31727643, 31727645, 31727647, 31727649, 31727651, 31727653, + 31727655, 31727657, 31727659, 31727661, 31727663, 31727665, 31727667, 31727669, 31727671, 31727673, 31727675, 31727677, 31727679, 31727681, 31727683, + 31727685, 31727687, 31727689, 31727691, 31727693, 31727695, 31727697, 31727699, 31727701, 31727703, 31727705, 31727707, 31727709, 31727711, 31727713, + 31727715, 31727717, 31727719, 31727721, 31727723, 31727725, 31727727, 31727729, 31727731, 31727733, 31727735, 31727737, 31727739, 31727741, 31727743, + 31752065, 31752067, 31752069, 31752071, 31752073, 31752075, 31752077, 31752079, 31752081, 31752083, 31752085, 31752087, 31752089, 31752091, 31752093, + 31752095, 31752097, 31752099, 31752101, 31752103, 31752105, 31752107, 31752109, 31752111, 31752113, 31752115, 31752117, 31752119, 31752121, 31752123, + 31752125, 31752127, 31752129, 31752131, 31752133, 31752135, 31752137, 31752139, 31752141, 31752143, 31752145, 31752147, 31752149, 31752151, 31752153, + 31752155, 31752157, 31752159, 31752161, 31752163, 31752165, 31752167, 31752169, 31752171, 31752173, 31752175, 31752177, 31752179, 31752181, 31752183, + 31752185, 31752187, 14389, 919, 0, 918, 14388, 31744007, 31744009, 31744011, 31744013, 31744015, 31744017, 31744019, 31744021, + 31744023, 31744025, 31744027, 31744029, 31744031, 31744033, 31744035, 31744037, 31744039, 31744041, 31744043, 31744045, 31744047, 31744049, 31744051, + 31744053, 31744055, 31744057, 31744059, 31744061, 31744063, 31744065, 31744067, 31744069, 31744071, 31744073, 31744075, 31744077, 31744079, 31744081, + 31744083, 31744085, 31744087, 31744089, 31744091, 31744093, 31744095, 31744097, 31744099, 31744101, 31744103, 31744105, 31744107, 31744109, 31744111, + 31744113, 31744115, 31744117, 31744119, 31744121, 31744123, 31744125, 31744127, 31768449, 31768451, 31768453, 31768455, 31768457, 31768459, 31768461, + 31768463, 31768465, 31768467, 31768469, 31768471, 31768473, 31768475, 31768477, 31768479, 31768481, 31768483, 31768485, 31768487, 31768489, 31768491, + 31768493, 31768495, 31768497, 31768499, 31768501, 31768503, 31768505, 31768507, 31768509, 31768511, 31768513, 31768515, 31768517, 31768519, 31768521, + 31768523, 31768525, 31768527, 31768529, 31768531, 31768533, 31768535, 31768537, 31768539, 31768541, 31768543, 31768545, 31768547, 31768549, 31768551, + 31768553, 31768555, 31768557, 31768559, 31768561, 31768563, 31768565, 31768567, 31768569, 31768571, 28691, 1827, 0, 1826, 28690, + 31760391, 31760393, 31760395, 31760397, 31760399, 31760401, 31760403, 31760405, 31760407, 31760409, 31760411, 31760413, 31760415, 31760417, 31760419, + 31760421, 31760423, 31760425, 31760427, 31760429, 31760431, 31760433, 31760435, 31760437, 31760439, 31760441, 31760443, 31760445, 31760447, 31760449, + 31760451, 31760453, 31760455, 31760457, 31760459, 31760461, 31760463, 31760465, 31760467, 31760469, 31760471, 31760473, 31760475, 31760477, 31760479, + 31760481, 31760483, 31760485, 31760487, 31760489, 31760491, 31760493, 31760495, 31760497, 31760499, 31760501, 31760503, 31760505, 31760507, 31760509, + 31760511, 31784833, 31784835, 31784837, 31784839, 31784841, 31784843, 31784845, 31784847, 31784849, 31784851, 31784853, 31784855, 31784857, 31784859, + 31784861, 31784863, 31784865, 31784867, 31784869, 31784871, 31784873, 31784875, 31784877, 31784879, 31784881, 31784883, 31784885, 31784887, 31784889, + 31784891, 31784893, 31784895, 31784897, 31784899, 31784901, 31784903, 31784905, 31784907, 31784909, 31784911, 31784913, 31784915, 31784917, 31784919, + 31784921, 31784923, 31784925, 31784927, 31784929, 31784931, 31784933, 31784935, 31784937, 31784939, 31784941, 31784943, 31784945, 31784947, 31784949, + 31784951, 31784953, 31784955, 57415, 1825, 0, 1824, 57414, 31776775, 31776777, 31776779, 31776781, 31776783, 31776785, 31776787, + 31776789, 31776791, 31776793, 31776795, 31776797, 31776799, 31776801, 31776803, 31776805, 31776807, 31776809, 31776811, 31776813, 31776815, 31776817, + 31776819, 31776821, 31776823, 31776825, 31776827, 31776829, 31776831, 31776833, 31776835, 31776837, 31776839, 31776841, 31776843, 31776845, 31776847, + 31776849, 31776851, 31776853, 31776855, 31776857, 31776859, 31776861, 31776863, 31776865, 31776867, 31776869, 31776871, 31776873, 31776875, 31776877, + 31776879, 31776881, 31776883, 31776885, 31776887, 31776889, 31776891, 31776893, 31776895, 31801217, 31801219, 31801221, 31801223, 31801225, 31801227, + 31801229, 31801231, 31801233, 31801235, 31801237, 31801239, 31801241, 31801243, 31801245, 31801247, 31801249, 31801251, 31801253, 31801255, 31801257, + 31801259, 31801261, 31801263, 31801265, 31801267, 31801269, 31801271, 31801273, 31801275, 31801277, 31801279, 31801281, 31801283, 31801285, 31801287, + 31801289, 31801291, 31801293, 31801295, 31801297, 31801299, 31801301, 31801303, 31801305, 31801307, 31801309, 31801311, 31801313, 31801315, 31801317, + 31801319, 31801321, 31801323, 31801325, 31801327, 31801329, 31801331, 31801333, 31801335, 31801337, 31801339, 31801341, 1819, 0, 1818, + 31793157, 31793159, 31793161, 31793163, 31793165, 31793167, 31793169, 31793171, 31793173, 31793175, 31793177, 31793179, 31793181, 31793183, 31793185, + 31793187, 31793189, 31793191, 31793193, 31793195, 31793197, 31793199, 31793201, 31793203, 31793205, 31793207, 31793209, 31793211, 31793213, 31793215, + 31793217, 31793219, 31793221, 31793223, 31793225, 31793227, 31793229, 31793231, 31793233, 31793235, 31793237, 31793239, 31793241, 31793243, 31793245, + 31793247, 31793249, 31793251, 31793253, 31793255, 31793257, 31793259, 31793261, 31793263, 31793265, 31793267, 31793269, 31793271, 31793273, 31793275, + 31793277, 31793279, 31817601, 31817603, 31817605, 31817607, 31817609, 31817611, 31817613, 31817615, 31817617, 31817619, 31817621, 31817623, 31817625, + 31817627, 31817629, 31817631, 31817633, 31817635, 31817637, 31817639, 31817641, 31817643, 31817645, 31817647, 31817649, 31817651, 31817653, 31817655, + 31817657, 31817659, 31817661, 31817663, 31817665, 31817667, 31817669, 31817671, 31817673, 31817675, 31817677, 31817679, 31817681, 31817683, 31817685, + 31817687, 31817689, 31817691, 31817693, 31817695, 31817697, 31817699, 31817701, 31817703, 31817705, 31817707, 31817709, 31817711, 31817713, 31817715, + 31817717, 31817719, 31817721, 31817723, 31817725, 3621, 0, 3620, 31809541, 31809543, 31809545, 31809547, 31809549, 31809551, 31809553, + 31809555, 31809557, 31809559, 31809561, 31809563, 31809565, 31809567, 31809569, 31809571, 31809573, 31809575, 31809577, 31809579, 31809581, 31809583, + 31809585, 31809587, 31809589, 31809591, 31809593, 31809595, 31809597, 31809599, 31809601, 31809603, 31809605, 31809607, 31809609, 31809611, 31809613, + 31809615, 31809617, 31809619, 31809621, 31809623, 31809625, 31809627, 31809629, 31809631, 31809633, 31809635, 31809637, 31809639, 31809641, 31809643, + 31809645, 31809647, 31809649, 31809651, 31809653, 31809655, 31809657, 31809659, 31809661, 31809663, 31833985, 31833987, 31833989, 31833991, 31833993, + 31833995, 31833997, 31833999, 31834001, 31834003, 31834005, 31834007, 31834009, 31834011, 31834013, 31834015, 31834017, 31834019, 31834021, 31834023, + 31834025, 31834027, 31834029, 31834031, 31834033, 31834035, 31834037, 31834039, 31834041, 31834043, 31834045, 31834047, 31834049, 31834051, 31834053, + 31834055, 31834057, 31834059, 31834061, 31834063, 31834065, 31834067, 31834069, 31834071, 31834073, 31834075, 31834077, 31834079, 31834081, 31834083, + 31834085, 31834087, 31834089, 31834091, 31834093, 31834095, 31834097, 31834099, 31834101, 31834103, 31834105, 31834107, 31834109, 3625, 0, + 3624, 31825925, 31825927, 31825929, 31825931, 31825933, 31825935, 31825937, 31825939, 31825941, 31825943, 31825945, 31825947, 31825949, 31825951, + 31825953, 31825955, 31825957, 31825959, 31825961, 31825963, 31825965, 31825967, 31825969, 31825971, 31825973, 31825975, 31825977, 31825979, 31825981, + 31825983, 31825985, 31825987, 31825989, 31825991, 31825993, 31825995, 31825997, 31825999, 31826001, 31826003, 31826005, 31826007, 31826009, 31826011, + 31826013, 31826015, 31826017, 31826019, 31826021, 31826023, 31826025, 31826027, 31826029, 31826031, 31826033, 31826035, 31826037, 31826039, 31826041, + 31826043, 31826045, 31826047, 31850369, 31850371, 31850373, 31850375, 31850377, 31850379, 31850381, 31850383, 31850385, 31850387, 31850389, 31850391, + 31850393, 31850395, 31850397, 31850399, 31850401, 31850403, 31850405, 31850407, 31850409, 31850411, 31850413, 31850415, 31850417, 31850419, 31850421, + 31850423, 31850425, 31850427, 31850429, 31850431, 31850433, 31850435, 31850437, 31850439, 31850441, 31850443, 31850445, 31850447, 31850449, 31850451, + 31850453, 31850455, 31850457, 31850459, 31850461, 31850463, 31850465, 31850467, 31850469, 31850471, 31850473, 31850475, 31850477, 31850479, 31850481, + 31850483, 31850485, 31850487, 31850489, 31850491, 31850493, 7219, 0, 7218, 31842309, 31842311, 31842313, 31842315, 31842317, 31842319, + 31842321, 31842323, 31842325, 31842327, 31842329, 31842331, 31842333, 31842335, 31842337, 31842339, 31842341, 31842343, 31842345, 31842347, 31842349, + 31842351, 31842353, 31842355, 31842357, 31842359, 31842361, 31842363, 31842365, 31842367, 31842369, 31842371, 31842373, 31842375, 31842377, 31842379, + 31842381, 31842383, 31842385, 31842387, 31842389, 31842391, 31842393, 31842395, 31842397, 31842399, 31842401, 31842403, 31842405, 31842407, 31842409, + 31842411, 31842413, 31842415, 31842417, 31842419, 31842421, 31842423, 31842425, 31842427, 31842429, 31842431, 31866753, 31866755, 31866757, 31866759, + 31866761, 31866763, 31866765, 31866767, 31866769, 31866771, 31866773, 31866775, 31866777, 31866779, 31866781, 31866783, 31866785, 31866787, 31866789, + 31866791, 31866793, 31866795, 31866797, 31866799, 31866801, 31866803, 31866805, 31866807, 31866809, 31866811, 31866813, 31866815, 31866817, 31866819, + 31866821, 31866823, 31866825, 31866827, 31866829, 31866831, 31866833, 31866835, 31866837, 31866839, 31866841, 31866843, 31866845, 31866847, 31866849, + 31866851, 31866853, 31866855, 31866857, 31866859, 31866861, 31866863, 31866865, 31866867, 31866869, 31866871, 31866873, 31866875, 31866877, 7217, + 0, 7216, 31858693, 31858695, 31858697, 31858699, 31858701, 31858703, 31858705, 31858707, 31858709, 31858711, 31858713, 31858715, 31858717, + 31858719, 31858721, 31858723, 31858725, 31858727, 31858729, 31858731, 31858733, 31858735, 31858737, 31858739, 31858741, 31858743, 31858745, 31858747, + 31858749, 31858751, 31858753, 31858755, 31858757, 31858759, 31858761, 31858763, 31858765, 31858767, 31858769, 31858771, 31858773, 31858775, 31858777, + 31858779, 31858781, 31858783, 31858785, 31858787, 31858789, 31858791, 31858793, 31858795, 31858797, 31858799, 31858801, 31858803, 31858805, 31858807, + 31858809, 31858811, 31858813, 31858815, 31883137, 31883139, 31883141, 31883143, 31883145, 31883147, 31883149, 31883151, 31883153, 31883155, 31883157, + 31883159, 31883161, 31883163, 31883165, 31883167, 31883169, 31883171, 31883173, 31883175, 31883177, 31883179, 31883181, 31883183, 31883185, 31883187, + 31883189, 31883191, 31883193, 31883195, 31883197, 31883199, 31883201, 31883203, 31883205, 31883207, 31883209, 31883211, 31883213, 31883215, 31883217, + 31883219, 31883221, 31883223, 31883225, 31883227, 31883229, 31883231, 31883233, 31883235, 31883237, 31883239, 31883241, 31883243, 31883245, 31883247, + 31883249, 31883251, 31883253, 31883255, 31883257, 31883259, 31883261, 7215, 0, 7214, 31875077, 31875079, 31875081, 31875083, 31875085, + 31875087, 31875089, 31875091, 31875093, 31875095, 31875097, 31875099, 31875101, 31875103, 31875105, 31875107, 31875109, 31875111, 31875113, 31875115, + 31875117, 31875119, 31875121, 31875123, 31875125, 31875127, 31875129, 31875131, 31875133, 31875135, 31875137, 31875139, 31875141, 31875143, 31875145, + 31875147, 31875149, 31875151, 31875153, 31875155, 31875157, 31875159, 31875161, 31875163, 31875165, 31875167, 31875169, 31875171, 31875173, 31875175, + 31875177, 31875179, 31875181, 31875183, 31875185, 31875187, 31875189, 31875191, 31875193, 31875195, 31875197, 31875199, 31899521, 31899523, 31899525, + 31899527, 31899529, 31899531, 31899533, 31899535, 31899537, 31899539, 31899541, 31899543, 31899545, 31899547, 31899549, 31899551, 31899553, 31899555, + 31899557, 31899559, 31899561, 31899563, 31899565, 31899567, 31899569, 31899571, 31899573, 31899575, 31899577, 31899579, 31899581, 31899583, 31899585, + 31899587, 31899589, 31899591, 31899593, 31899595, 31899597, 31899599, 31899601, 31899603, 31899605, 31899607, 31899609, 31899611, 31899613, 31899615, + 31899617, 31899619, 31899621, 31899623, 31899625, 31899627, 31899629, 31899631, 31899633, 31899635, 31899637, 31899639, 31899641, 31899643, 31899645, + 14387, 0, 14386, 31891461, 31891463, 31891465, 31891467, 31891469, 31891471, 31891473, 31891475, 31891477, 31891479, 31891481, 31891483, + 31891485, 31891487, 31891489, 31891491, 31891493, 31891495, 31891497, 31891499, 31891501, 31891503, 31891505, 31891507, 31891509, 31891511, 31891513, + 31891515, 31891517, 31891519, 31891521, 31891523, 31891525, 31891527, 31891529, 31891531, 31891533, 31891535, 31891537, 31891539, 31891541, 31891543, + 31891545, 31891547, 31891549, 31891551, 31891553, 31891555, 31891557, 31891559, 31891561, 31891563, 31891565, 31891567, 31891569, 31891571, 31891573, + 31891575, 31891577, 31891579, 31891581, 31891583, 31915905, 31915907, 31915909, 31915911, 31915913, 31915915, 31915917, 31915919, 31915921, 31915923, + 31915925, 31915927, 31915929, 31915931, 31915933, 31915935, 31915937, 31915939, 31915941, 31915943, 31915945, 31915947, 31915949, 31915951, 31915953, + 31915955, 31915957, 31915959, 31915961, 31915963, 31915965, 31915967, 31915969, 31915971, 31915973, 31915975, 31915977, 31915979, 31915981, 31915983, + 31915985, 31915987, 31915989, 31915991, 31915993, 31915995, 31915997, 31915999, 31916001, 31916003, 31916005, 31916007, 31916009, 31916011, 31916013, + 31916015, 31916017, 31916019, 31916021, 31916023, 31916025, 31916027, 31916029, 14385, 0, 14384, 31907845, 31907847, 31907849, 31907851, + 31907853, 31907855, 31907857, 31907859, 31907861, 31907863, 31907865, 31907867, 31907869, 31907871, 31907873, 31907875, 31907877, 31907879, 31907881, + 31907883, 31907885, 31907887, 31907889, 31907891, 31907893, 31907895, 31907897, 31907899, 31907901, 31907903, 31907905, 31907907, 31907909, 31907911, + 31907913, 31907915, 31907917, 31907919, 31907921, 31907923, 31907925, 31907927, 31907929, 31907931, 31907933, 31907935, 31907937, 31907939, 31907941, + 31907943, 31907945, 31907947, 31907949, 31907951, 31907953, 31907955, 31907957, 31907959, 31907961, 31907963, 31907965, 31907967, 31932289, 31932291, + 31932293, 31932295, 31932297, 31932299, 31932301, 31932303, 31932305, 31932307, 31932309, 31932311, 31932313, 31932315, 31932317, 31932319, 31932321, + 31932323, 31932325, 31932327, 31932329, 31932331, 31932333, 31932335, 31932337, 31932339, 31932341, 31932343, 31932345, 31932347, 31932349, 31932351, + 31932353, 31932355, 31932357, 31932359, 31932361, 31932363, 31932365, 31932367, 31932369, 31932371, 31932373, 31932375, 31932377, 31932379, 31932381, + 31932383, 31932385, 31932387, 31932389, 31932391, 31932393, 31932395, 31932397, 31932399, 31932401, 31932403, 31932405, 31932407, 31932409, 31932411, + 31932413, 28687, 0, 28686, 31924229, 31924231, 31924233, 31924235, 31924237, 31924239, 31924241, 31924243, 31924245, 31924247, 31924249, + 31924251, 31924253, 31924255, 31924257, 31924259, 31924261, 31924263, 31924265, 31924267, 31924269, 31924271, 31924273, 31924275, 31924277, 31924279, + 31924281, 31924283, 31924285, 31924287, 31924289, 31924291, 31924293, 31924295, 31924297, 31924299, 31924301, 31924303, 31924305, 31924307, 31924309, + 31924311, 31924313, 31924315, 31924317, 31924319, 31924321, 31924323, 31924325, 31924327, 31924329, 31924331, 31924333, 31924335, 31924337, 31924339, + 31924341, 31924343, 31924345, 31924347, 31924349, 31924351, 31948673, 31948675, 31948677, 31948679, 31948681, 31948683, 31948685, 31948687, 31948689, + 31948691, 31948693, 31948695, 31948697, 31948699, 31948701, 31948703, 31948705, 31948707, 31948709, 31948711, 31948713, 31948715, 31948717, 31948719, + 31948721, 31948723, 31948725, 31948727, 31948729, 31948731, 31948733, 31948735, 31948737, 31948739, 31948741, 31948743, 31948745, 31948747, 31948749, + 31948751, 31948753, 31948755, 31948757, 31948759, 31948761, 31948763, 31948765, 31948767, 31948769, 31948771, 31948773, 31948775, 31948777, 31948779, + 31948781, 31948783, 31948785, 31948787, 31948789, 31948791, 31948793, 31948795, 31948797, 114865, 0, 114864, 31940613, 31940615, 31940617, + 31940619, 31940621, 31940623, 31940625, 31940627, 31940629, 31940631, 31940633, 31940635, 31940637, 31940639, 31940641, 31940643, 31940645, 31940647, + 31940649, 31940651, 31940653, 31940655, 31940657, 31940659, 31940661, 31940663, 31940665, 31940667, 31940669, 31940671, 31940673, 31940675, 31940677, + 31940679, 31940681, 31940683, 31940685, 31940687, 31940689, 31940691, 31940693, 31940695, 31940697, 31940699, 31940701, 31940703, 31940705, 31940707, + 31940709, 31940711, 31940713, 31940715, 31940717, 31940719, 31940721, 31940723, 31940725, 31940727, 31940729, 31940731, 31940733, 31940735, 31965057, + 31965059, 31965061, 31965063, 31965065, 31965067, 31965069, 31965071, 31965073, 31965075, 31965077, 31965079, 31965081, 31965083, 31965085, 31965087, + 31965089, 31965091, 31965093, 31965095, 31965097, 31965099, 31965101, 31965103, 31965105, 31965107, 31965109, 31965111, 31965113, 31965115, 31965117, + 31965119, 31965121, 31965123, 31965125, 31965127, 31965129, 31965131, 31965133, 31965135, 31965137, 31965139, 31965141, 31965143, 31965145, 31965147, + 31965149, 31965151, 31965153, 31965155, 31965157, 31965159, 31965161, 31965163, 31965165, 31965167, 31965169, 31965171, 31965173, 31965175, 31965177, + 31965179, 31965181, 31965183, 0, 31956995, 31956997, 31956999, 31957001, 31957003, 31957005, 31957007, 31957009, 31957011, 31957013, 31957015, + 31957017, 31957019, 31957021, 31957023, 31957025, 31957027, 31957029, 31957031, 31957033, 31957035, 31957037, 31957039, 31957041, 31957043, 31957045, + 31957047, 31957049, 31957051, 31957053, 31957055, 31957057, 31957059, 31957061, 31957063, 31957065, 31957067, 31957069, 31957071, 31957073, 31957075, + 31957077, 31957079, 31957081, 31957083, 31957085, 31957087, 31957089, 31957091, 31957093, 31957095, 31957097, 31957099, 31957101, 31957103, 31957105, + 31957107, 31957109, 31957111, 31957113, 31957115, 31957117, 31957119, 31981441, 31981443, 31981445, 31981447, 31981449, 31981451, 31981453, 31981455, + 31981457, 31981459, 31981461, 31981463, 31981465, 31981467, 31981469, 31981471, 31981473, 31981475, 31981477, 31981479, 31981481, 31981483, 31981485, + 31981487, 31981489, 31981491, 31981493, 31981495, 31981497, 31981499, 31981501, 31981503, 31981505, 31981507, 31981509, 31981511, 31981513, 31981515, + 31981517, 31981519, 31981521, 31981523, 31981525, 31981527, 31981529, 31981531, 31981533, 31981535, 31981537, 31981539, 31981541, 31981543, 31981545, + 31981547, 31981549, 31981551, 31981553, 31981555, 31981557, 31981559, 31981561, 31981563, 31981565, 31981567, 0, 31973379, 31973381, 31973383, + 31973385, 31973387, 31973389, 31973391, 31973393, 31973395, 31973397, 31973399, 31973401, 31973403, 31973405, 31973407, 31973409, 31973411, 31973413, + 31973415, 31973417, 31973419, 31973421, 31973423, 31973425, 31973427, 31973429, 31973431, 31973433, 31973435, 31973437, 31973439, 31973441, 31973443, + 31973445, 31973447, 31973449, 31973451, 31973453, 31973455, 31973457, 31973459, 31973461, 31973463, 31973465, 31973467, 31973469, 31973471, 31973473, + 31973475, 31973477, 31973479, 31973481, 31973483, 31973485, 31973487, 31973489, 31973491, 31973493, 31973495, 31973497, 31973499, 31973501, 31973503, + 31997825, 31997827, 31997829, 31997831, 31997833, 31997835, 31997837, 31997839, 31997841, 31997843, 31997845, 31997847, 31997849, 31997851, 31997853, + 31997855, 31997857, 31997859, 31997861, 31997863, 31997865, 31997867, 31997869, 31997871, 31997873, 31997875, 31997877, 31997879, 31997881, 31997883, + 31997885, 31997887, 31997889, 31997891, 31997893, 31997895, 31997897, 31997899, 31997901, 31997903, 31997905, 31997907, 31997909, 31997911, 31997913, + 31997915, 31997917, 31997919, 31997921, 31997923, 31997925, 31997927, 31997929, 31997931, 31997933, 31997935, 31997937, 31997939, 31997941, 31997943, + 31997945, 31997947, 31997949, 31997951, 0, 31989763, 31989765, 31989767, 31989769, 31989771, 31989773, 31989775, 31989777, 31989779, 31989781, + 31989783, 31989785, 31989787, 31989789, 31989791, 31989793, 31989795, 31989797, 31989799, 31989801, 31989803, 31989805, 31989807, 31989809, 31989811, + 31989813, 31989815, 31989817, 31989819, 31989821, 31989823, 31989825, 31989827, 31989829, 31989831, 31989833, 31989835, 31989837, 31989839, 31989841, + 31989843, 31989845, 31989847, 31989849, 31989851, 31989853, 31989855, 31989857, 31989859, 31989861, 31989863, 31989865, 31989867, 31989869, 31989871, + 31989873, 31989875, 31989877, 31989879, 31989881, 31989883, 31989885, 31989887, 32014209, 32014211, 32014213, 32014215, 32014217, 32014219, 32014221, + 32014223, 32014225, 32014227, 32014229, 32014231, 32014233, 32014235, 32014237, 32014239, 32014241, 32014243, 32014245, 32014247, 32014249, 32014251, + 32014253, 32014255, 32014257, 32014259, 32014261, 32014263, 32014265, 32014267, 32014269, 32014271, 32014273, 32014275, 32014277, 32014279, 32014281, + 32014283, 32014285, 32014287, 32014289, 32014291, 32014293, 32014295, 32014297, 32014299, 32014301, 32014303, 32014305, 32014307, 32014309, 32014311, + 32014313, 32014315, 32014317, 32014319, 32014321, 32014323, 32014325, 32014327, 32014329, 32014331, 32014333, 32014335, 0, 32006147, 32006149, + 32006151, 32006153, 32006155, 32006157, 32006159, 32006161, 32006163, 32006165, 32006167, 32006169, 32006171, 32006173, 32006175, 32006177, 32006179, + 32006181, 32006183, 32006185, 32006187, 32006189, 32006191, 32006193, 32006195, 32006197, 32006199, 32006201, 32006203, 32006205, 32006207, 32006209, + 32006211, 32006213, 32006215, 32006217, 32006219, 32006221, 32006223, 32006225, 32006227, 32006229, 32006231, 32006233, 32006235, 32006237, 32006239, + 32006241, 32006243, 32006245, 32006247, 32006249, 32006251, 32006253, 32006255, 32006257, 32006259, 32006261, 32006263, 32006265, 32006267, 32006269, + 32006271, 32030593, 32030595, 32030597, 32030599, 32030601, 32030603, 32030605, 32030607, 32030609, 32030611, 32030613, 32030615, 32030617, 32030619, + 32030621, 32030623, 32030625, 32030627, 32030629, 32030631, 32030633, 32030635, 32030637, 32030639, 32030641, 32030643, 32030645, 32030647, 32030649, + 32030651, 32030653, 32030655, 32030657, 32030659, 32030661, 32030663, 32030665, 32030667, 32030669, 32030671, 32030673, 32030675, 32030677, 32030679, + 32030681, 32030683, 32030685, 32030687, 32030689, 32030691, 32030693, 32030695, 32030697, 32030699, 32030701, 32030703, 32030705, 32030707, 32030709, + 32030711, 32030713, 32030715, 32030717, 32030719, 0, 32022531, 32022533, 32022535, 32022537, 32022539, 32022541, 32022543, 32022545, 32022547, + 32022549, 32022551, 32022553, 32022555, 32022557, 32022559, 32022561, 32022563, 32022565, 32022567, 32022569, 32022571, 32022573, 32022575, 32022577, + 32022579, 32022581, 32022583, 32022585, 32022587, 32022589, 32022591, 32022593, 32022595, 32022597, 32022599, 32022601, 32022603, 32022605, 32022607, + 32022609, 32022611, 32022613, 32022615, 32022617, 32022619, 32022621, 32022623, 32022625, 32022627, 32022629, 32022631, 32022633, 32022635, 32022637, + 32022639, 32022641, 32022643, 32022645, 32022647, 32022649, 32022651, 32022653, 32022655, 32046977, 32046979, 32046981, 32046983, 32046985, 32046987, + 32046989, 32046991, 32046993, 32046995, 32046997, 32046999, 32047001, 32047003, 32047005, 32047007, 32047009, 32047011, 32047013, 32047015, 32047017, + 32047019, 32047021, 32047023, 32047025, 32047027, 32047029, 32047031, 32047033, 32047035, 32047037, 32047039, 32047041, 32047043, 32047045, 32047047, + 32047049, 32047051, 32047053, 32047055, 32047057, 32047059, 32047061, 32047063, 32047065, 32047067, 32047069, 32047071, 32047073, 32047075, 32047077, + 32047079, 32047081, 32047083, 32047085, 32047087, 32047089, 32047091, 32047093, 32047095, 32047097, 32047099, 32047101, 32047103, 0, 32038915, + 32038917, 32038919, 32038921, 32038923, 32038925, 32038927, 32038929, 32038931, 32038933, 32038935, 32038937, 32038939, 32038941, 32038943, 32038945, + 32038947, 32038949, 32038951, 32038953, 32038955, 32038957, 32038959, 32038961, 32038963, 32038965, 32038967, 32038969, 32038971, 32038973, 32038975, + 32038977, 32038979, 32038981, 32038983, 32038985, 32038987, 32038989, 32038991, 32038993, 32038995, 32038997, 32038999, 32039001, 32039003, 32039005, + 32039007, 32039009, 32039011, 32039013, 32039015, 32039017, 32039019, 32039021, 32039023, 32039025, 32039027, 32039029, 32039031, 32039033, 32039035, + 32039037, 32039039, 32063361, 32063363, 32063365, 32063367, 32063369, 32063371, 32063373, 32063375, 32063377, 32063379, 32063381, 32063383, 32063385, + 32063387, 32063389, 32063391, 32063393, 32063395, 32063397, 32063399, 32063401, 32063403, 32063405, 32063407, 32063409, 32063411, 32063413, 32063415, + 32063417, 32063419, 32063421, 32063423, 32063425, 32063427, 32063429, 32063431, 32063433, 32063435, 32063437, 32063439, 32063441, 32063443, 32063445, + 32063447, 32063449, 32063451, 32063453, 32063455, 32063457, 32063459, 32063461, 32063463, 32063465, 32063467, 32063469, 32063471, 32063473, 32063475, + 32063477, 32063479, 32063481, 32063483, 32063485, 32063487, 0, 32055299, 32055301, 32055303, 32055305, 32055307, 32055309, 32055311, 32055313, + 32055315, 32055317, 32055319, 32055321, 32055323, 32055325, 32055327, 32055329, 32055331, 32055333, 32055335, 32055337, 32055339, 32055341, 32055343, + 32055345, 32055347, 32055349, 32055351, 32055353, 32055355, 32055357, 32055359, 32055361, 32055363, 32055365, 32055367, 32055369, 32055371, 32055373, + 32055375, 32055377, 32055379, 32055381, 32055383, 32055385, 32055387, 32055389, 32055391, 32055393, 32055395, 32055397, 32055399, 32055401, 32055403, + 32055405, 32055407, 32055409, 32055411, 32055413, 32055415, 32055417, 32055419, 32055421, 32055423, 32079745, 32079747, 32079749, 32079751, 32079753, + 32079755, 32079757, 32079759, 32079761, 32079763, 32079765, 32079767, 32079769, 32079771, 32079773, 32079775, 32079777, 32079779, 32079781, 32079783, + 32079785, 32079787, 32079789, 32079791, 32079793, 32079795, 32079797, 32079799, 32079801, 32079803, 32079805, 32079807, 32079809, 32079811, 32079813, + 32079815, 32079817, 32079819, 32079821, 32079823, 32079825, 32079827, 32079829, 32079831, 32079833, 32079835, 32079837, 32079839, 32079841, 32079843, + 32079845, 32079847, 32079849, 32079851, 32079853, 32079855, 32079857, 32079859, 32079861, 32079863, 32079865, 32079867, 32079869, 32079871, 0, + 32071683, 32071685, 32071687, 32071689, 32071691, 32071693, 32071695, 32071697, 32071699, 32071701, 32071703, 32071705, 32071707, 32071709, 32071711, + 32071713, 32071715, 32071717, 32071719, 32071721, 32071723, 32071725, 32071727, 32071729, 32071731, 32071733, 32071735, 32071737, 32071739, 32071741, + 32071743, 32071745, 32071747, 32071749, 32071751, 32071753, 32071755, 32071757, 32071759, 32071761, 32071763, 32071765, 32071767, 32071769, 32071771, + 32071773, 32071775, 32071777, 32071779, 32071781, 32071783, 32071785, 32071787, 32071789, 32071791, 32071793, 32071795, 32071797, 32071799, 32071801, + 32071803, 32071805, 32071807, 32096129, 32096131, 32096133, 32096135, 32096137, 32096139, 32096141, 32096143, 32096145, 32096147, 32096149, 32096151, + 32096153, 32096155, 32096157, 32096159, 32096161, 32096163, 32096165, 32096167, 32096169, 32096171, 32096173, 32096175, 32096177, 32096179, 32096181, + 32096183, 32096185, 32096187, 32096189, 32096191, 32096193, 32096195, 32096197, 32096199, 32096201, 32096203, 32096205, 32096207, 32096209, 32096211, + 32096213, 32096215, 32096217, 32096219, 32096221, 32096223, 32096225, 32096227, 32096229, 32096231, 32096233, 32096235, 32096237, 32096239, 32096241, + 32096243, 32096245, 32096247, 32096249, 32096251, 32096253, 32096255, 0, 32088067, 32088069, 32088071, 32088073, 32088075, 32088077, 32088079, + 32088081, 32088083, 32088085, 32088087, 32088089, 32088091, 32088093, 32088095, 32088097, 32088099, 32088101, 32088103, 32088105, 32088107, 32088109, + 32088111, 32088113, 32088115, 32088117, 32088119, 32088121, 32088123, 32088125, 32088127, 32088129, 32088131, 32088133, 32088135, 32088137, 32088139, + 32088141, 32088143, 32088145, 32088147, 32088149, 32088151, 32088153, 32088155, 32088157, 32088159, 32088161, 32088163, 32088165, 32088167, 32088169, + 32088171, 32088173, 32088175, 32088177, 32088179, 32088181, 32088183, 32088185, 32088187, 32088189, 32088191, 32112513, 32112515, 32112517, 32112519, + 32112521, 32112523, 32112525, 32112527, 32112529, 32112531, 32112533, 32112535, 32112537, 32112539, 32112541, 32112543, 32112545, 32112547, 32112549, + 32112551, 32112553, 32112555, 32112557, 32112559, 32112561, 32112563, 32112565, 32112567, 32112569, 32112571, 32112573, 32112575, 32112577, 32112579, + 32112581, 32112583, 32112585, 32112587, 32112589, 32112591, 32112593, 32112595, 32112597, 32112599, 32112601, 32112603, 32112605, 32112607, 32112609, + 32112611, 32112613, 32112615, 32112617, 32112619, 32112621, 32112623, 32112625, 32112627, 32112629, 32112631, 32112633, 32112635, 32112637, 32112639, + 0, 32104451, 32104453, 32104455, 32104457, 32104459, 32104461, 32104463, 32104465, 32104467, 32104469, 32104471, 32104473, 32104475, 32104477, + 32104479, 32104481, 32104483, 32104485, 32104487, 32104489, 32104491, 32104493, 32104495, 32104497, 32104499, 32104501, 32104503, 32104505, 32104507, + 32104509, 32104511, 32104513, 32104515, 32104517, 32104519, 32104521, 32104523, 32104525, 32104527, 32104529, 32104531, 32104533, 32104535, 32104537, + 32104539, 32104541, 32104543, 32104545, 32104547, 32104549, 32104551, 32104553, 32104555, 32104557, 32104559, 32104561, 32104563, 32104565, 32104567, + 32104569, 32104571, 32104573, 32104575, 32128897, 32128899, 32128901, 32128903, 32128905, 32128907, 32128909, 32128911, 32128913, 32128915, 32128917, + 32128919, 32128921, 32128923, 32128925, 32128927, 32128929, 32128931, 32128933, 32128935, 32128937, 32128939, 32128941, 32128943, 32128945, 32128947, + 32128949, 32128951, 32128953, 32128955, 32128957, 32128959, 32128961, 32128963, 32128965, 32128967, 32128969, 32128971, 32128973, 32128975, 32128977, + 32128979, 32128981, 32128983, 32128985, 32128987, 32128989, 32128991, 32128993, 32128995, 32128997, 32128999, 32129001, 32129003, 32129005, 32129007, + 32129009, 32129011, 32129013, 32129015, 32129017, 32129019, 32129021, 32129023, 0, 32120835, 32120837, 32120839, 32120841, 32120843, 32120845, + 32120847, 32120849, 32120851, 32120853, 32120855, 32120857, 32120859, 32120861, 32120863, 32120865, 32120867, 32120869, 32120871, 32120873, 32120875, + 32120877, 32120879, 32120881, 32120883, 32120885, 32120887, 32120889, 32120891, 32120893, 32120895, 32120897, 32120899, 32120901, 32120903, 32120905, + 32120907, 32120909, 32120911, 32120913, 32120915, 32120917, 32120919, 32120921, 32120923, 32120925, 32120927, 32120929, 32120931, 32120933, 32120935, + 32120937, 32120939, 32120941, 32120943, 32120945, 32120947, 32120949, 32120951, 32120953, 32120955, 32120957, 32120959, 32145281, 32145283, 32145285, + 32145287, 32145289, 32145291, 32145293, 32145295, 32145297, 32145299, 32145301, 32145303, 32145305, 32145307, 32145309, 32145311, 32145313, 32145315, + 32145317, 32145319, 32145321, 32145323, 32145325, 32145327, 32145329, 32145331, 32145333, 32145335, 32145337, 32145339, 32145341, 32145343, 32145345, + 32145347, 32145349, 32145351, 32145353, 32145355, 32145357, 32145359, 32145361, 32145363, 32145365, 32145367, 32145369, 32145371, 32145373, 32145375, + 32145377, 32145379, 32145381, 32145383, 32145385, 32145387, 32145389, 32145391, 32145393, 32145395, 32145397, 32145399, 32145401, 32145403, 32145405, + 32145407, 0, 32137219, 32137221, 32137223, 32137225, 32137227, 32137229, 32137231, 32137233, 32137235, 32137237, 32137239, 32137241, 32137243, + 32137245, 32137247, 32137249, 32137251, 32137253, 32137255, 32137257, 32137259, 32137261, 32137263, 32137265, 32137267, 32137269, 32137271, 32137273, + 32137275, 32137277, 32137279, 32137281, 32137283, 32137285, 32137287, 32137289, 32137291, 32137293, 32137295, 32137297, 32137299, 32137301, 32137303, + 32137305, 32137307, 32137309, 32137311, 32137313, 32137315, 32137317, 32137319, 32137321, 32137323, 32137325, 32137327, 32137329, 32137331, 32137333, + 32137335, 32137337, 32137339, 32137341, 32137343, 32161665, 32161667, 32161669, 32161671, 32161673, 32161675, 32161677, 32161679, 32161681, 32161683, + 32161685, 32161687, 32161689, 32161691, 32161693, 32161695, 32161697, 32161699, 32161701, 32161703, 32161705, 32161707, 32161709, 32161711, 32161713, + 32161715, 32161717, 32161719, 32161721, 32161723, 32161725, 32161727, 32161729, 32161731, 32161733, 32161735, 32161737, 32161739, 32161741, 32161743, + 32161745, 32161747, 32161749, 32161751, 32161753, 32161755, 32161757, 32161759, 32161761, 32161763, 32161765, 32161767, 32161769, 32161771, 32161773, + 32161775, 32161777, 32161779, 32161781, 32161783, 32161785, 32161787, 32161789, 32161791, 0, 32153603, 32153605, 32153607, 32153609, 32153611, + 32153613, 32153615, 32153617, 32153619, 32153621, 32153623, 32153625, 32153627, 32153629, 32153631, 32153633, 32153635, 32153637, 32153639, 32153641, + 32153643, 32153645, 32153647, 32153649, 32153651, 32153653, 32153655, 32153657, 32153659, 32153661, 32153663, 32153665, 32153667, 32153669, 32153671, + 32153673, 32153675, 32153677, 32153679, 32153681, 32153683, 32153685, 32153687, 32153689, 32153691, 32153693, 32153695, 32153697, 32153699, 32153701, + 32153703, 32153705, 32153707, 32153709, 32153711, 32153713, 32153715, 32153717, 32153719, 32153721, 32153723, 32153725, 32153727, 32178049, 32178051, + 32178053, 32178055, 32178057, 32178059, 32178061, 32178063, 32178065, 32178067, 32178069, 32178071, 32178073, 32178075, 32178077, 32178079, 32178081, + 32178083, 32178085, 32178087, 32178089, 32178091, 32178093, 32178095, 32178097, 32178099, 32178101, 32178103, 32178105, 32178107, 32178109, 32178111, + 32178113, 32178115, 32178117, 32178119, 32178121, 32178123, 32178125, 32178127, 32178129, 32178131, 32178133, 32178135, 32178137, 32178139, 32178141, + 32178143, 32178145, 32178147, 32178149, 32178151, 32178153, 32178155, 32178157, 32178159, 32178161, 32178163, 32178165, 32178167, 32178169, 32178171, + 32178173, 32178175, 0, 32169987, 32169989, 32169991, 32169993, 32169995, 32169997, 32169999, 32170001, 32170003, 32170005, 32170007, 32170009, + 32170011, 32170013, 32170015, 32170017, 32170019, 32170021, 32170023, 32170025, 32170027, 32170029, 32170031, 32170033, 32170035, 32170037, 32170039, + 32170041, 32170043, 32170045, 32170047, 32170049, 32170051, 32170053, 32170055, 32170057, 32170059, 32170061, 32170063, 32170065, 32170067, 32170069, + 32170071, 32170073, 32170075, 32170077, 32170079, 32170081, 32170083, 32170085, 32170087, 32170089, 32170091, 32170093, 32170095, 32170097, 32170099, + 32170101, 32170103, 32170105, 32170107, 32170109, 32170111, 32194433, 32194435, 32194437, 32194439, 32194441, 32194443, 32194445, 32194447, 32194449, + 32194451, 32194453, 32194455, 32194457, 32194459, 32194461, 32194463, 32194465, 32194467, 32194469, 32194471, 32194473, 32194475, 32194477, 32194479, + 32194481, 32194483, 32194485, 32194487, 32194489, 32194491, 32194493, 32194495, 32194497, 32194499, 32194501, 32194503, 32194505, 32194507, 32194509, + 32194511, 32194513, 32194515, 32194517, 32194519, 32194521, 32194523, 32194525, 32194527, 32194529, 32194531, 32194533, 32194535, 32194537, 32194539, + 32194541, 32194543, 32194545, 32194547, 32194549, 32194551, 32194553, 32194555, 32194557, 32194559, 0, 32186371, 32186373, 32186375, 32186377, + 32186379, 32186381, 32186383, 32186385, 32186387, 32186389, 32186391, 32186393, 32186395, 32186397, 32186399, 32186401, 32186403, 32186405, 32186407, + 32186409, 32186411, 32186413, 32186415, 32186417, 32186419, 32186421, 32186423, 32186425, 32186427, 32186429, 32186431, 32186433, 32186435, 32186437, + 32186439, 32186441, 32186443, 32186445, 32186447, 32186449, 32186451, 32186453, 32186455, 32186457, 32186459, 32186461, 32186463, 32186465, 32186467, + 32186469, 32186471, 32186473, 32186475, 32186477, 32186479, 32186481, 32186483, 32186485, 32186487, 32186489, 32186491, 32186493, 32186495, 32210817, + 32210819, 32210821, 32210823, 32210825, 32210827, 32210829, 32210831, 32210833, 32210835, 32210837, 32210839, 32210841, 32210843, 32210845, 32210847, + 32210849, 32210851, 32210853, 32210855, 32210857, 32210859, 32210861, 32210863, 32210865, 32210867, 32210869, 32210871, 32210873, 32210875, 32210877, + 32210879, 32210881, 32210883, 32210885, 32210887, 32210889, 32210891, 32210893, 32210895, 32210897, 32210899, 32210901, 32210903, 32210905, 32210907, + 32210909, 32210911, 32210913, 32210915, 32210917, 32210919, 32210921, 32210923, 32210925, 32210927, 32210929, 32210931, 32210933, 32210935, 32210937, + 32210939, 32210941, 32210943, 0, 32202755, 32202757, 32202759, 32202761, 32202763, 32202765, 32202767, 32202769, 32202771, 32202773, 32202775, + 32202777, 32202779, 32202781, 32202783, 32202785, 32202787, 32202789, 32202791, 32202793, 32202795, 32202797, 32202799, 32202801, 32202803, 32202805, + 32202807, 32202809, 32202811, 32202813, 32202815, 32202817, 32202819, 32202821, 32202823, 32202825, 32202827, 32202829, 32202831, 32202833, 32202835, + 32202837, 32202839, 32202841, 32202843, 32202845, 32202847, 32202849, 32202851, 32202853, 32202855, 32202857, 32202859, 32202861, 32202863, 32202865, + 32202867, 32202869, 32202871, 32202873, 32202875, 32202877, 32202879, 32227201, 32227203, 32227205, 32227207, 32227209, 32227211, 32227213, 32227215, + 32227217, 32227219, 32227221, 32227223, 32227225, 32227227, 32227229, 32227231, 32227233, 32227235, 32227237, 32227239, 32227241, 32227243, 32227245, + 32227247, 32227249, 32227251, 32227253, 32227255, 32227257, 32227259, 32227261, 32227263, 32227265, 32227267, 32227269, 32227271, 32227273, 32227275, + 32227277, 32227279, 32227281, 32227283, 32227285, 32227287, 32227289, 32227291, 32227293, 32227295, 32227297, 32227299, 32227301, 32227303, 32227305, + 32227307, 32227309, 32227311, 32227313, 32227315, 32227317, 32227319, 32227321, 32227323, 32227325, 32227327, 0, 32219139, 32219141, 32219143, + 32219145, 32219147, 32219149, 32219151, 32219153, 32219155, 32219157, 32219159, 32219161, 32219163, 32219165, 32219167, 32219169, 32219171, 32219173, + 32219175, 32219177, 32219179, 32219181, 32219183, 32219185, 32219187, 32219189, 32219191, 32219193, 32219195, 32219197, 32219199, 32219201, 32219203, + 32219205, 32219207, 32219209, 32219211, 32219213, 32219215, 32219217, 32219219, 32219221, 32219223, 32219225, 32219227, 32219229, 32219231, 32219233, + 32219235, 32219237, 32219239, 32219241, 32219243, 32219245, 32219247, 32219249, 32219251, 32219253, 32219255, 32219257, 32219259, 32219261, 32219263, + 32243585, 32243587, 32243589, 32243591, 32243593, 32243595, 32243597, 32243599, 32243601, 32243603, 32243605, 32243607, 32243609, 32243611, 32243613, + 32243615, 32243617, 32243619, 32243621, 32243623, 32243625, 32243627, 32243629, 32243631, 32243633, 32243635, 32243637, 32243639, 32243641, 32243643, + 32243645, 32243647, 32243649, 32243651, 32243653, 32243655, 32243657, 32243659, 32243661, 32243663, 32243665, 32243667, 32243669, 32243671, 32243673, + 32243675, 32243677, 32243679, 32243681, 32243683, 32243685, 32243687, 32243689, 32243691, 32243693, 32243695, 32243697, 32243699, 32243701, 32243703, + 32243705, 32243707, 32243709, 32243711, 0, 32235523, 32235525, 32235527, 32235529, 32235531, 32235533, 32235535, 32235537, 32235539, 32235541, + 32235543, 32235545, 32235547, 32235549, 32235551, 32235553, 32235555, 32235557, 32235559, 32235561, 32235563, 32235565, 32235567, 32235569, 32235571, + 32235573, 32235575, 32235577, 32235579, 32235581, 32235583, 32235585, 32235587, 32235589, 32235591, 32235593, 32235595, 32235597, 32235599, 32235601, + 32235603, 32235605, 32235607, 32235609, 32235611, 32235613, 32235615, 32235617, 32235619, 32235621, 32235623, 32235625, 32235627, 32235629, 32235631, + 32235633, 32235635, 32235637, 32235639, 32235641, 32235643, 32235645, 32235647, 32259969, 32259971, 32259973, 32259975, 32259977, 32259979, 32259981, + 32259983, 32259985, 32259987, 32259989, 32259991, 32259993, 32259995, 32259997, 32259999, 32260001, 32260003, 32260005, 32260007, 32260009, 32260011, + 32260013, 32260015, 32260017, 32260019, 32260021, 32260023, 32260025, 32260027, 32260029, 32260031, 32260033, 32260035, 32260037, 32260039, 32260041, + 32260043, 32260045, 32260047, 32260049, 32260051, 32260053, 32260055, 32260057, 32260059, 32260061, 32260063, 32260065, 32260067, 32260069, 32260071, + 32260073, 32260075, 32260077, 32260079, 32260081, 32260083, 32260085, 32260087, 32260089, 32260091, 32260093, 32260095, 0, 32251907, 32251909, + 32251911, 32251913, 32251915, 32251917, 32251919, 32251921, 32251923, 32251925, 32251927, 32251929, 32251931, 32251933, 32251935, 32251937, 32251939, + 32251941, 32251943, 32251945, 32251947, 32251949, 32251951, 32251953, 32251955, 32251957, 32251959, 32251961, 32251963, 32251965, 32251967, 32251969, + 32251971, 32251973, 32251975, 32251977, 32251979, 32251981, 32251983, 32251985, 32251987, 32251989, 32251991, 32251993, 32251995, 32251997, 32251999, + 32252001, 32252003, 32252005, 32252007, 32252009, 32252011, 32252013, 32252015, 32252017, 32252019, 32252021, 32252023, 32252025, 32252027, 32252029, + 32252031, 32276353, 32276355, 32276357, 32276359, 32276361, 32276363, 32276365, 32276367, 32276369, 32276371, 32276373, 32276375, 32276377, 32276379, + 32276381, 32276383, 32276385, 32276387, 32276389, 32276391, 32276393, 32276395, 32276397, 32276399, 32276401, 32276403, 32276405, 32276407, 32276409, + 32276411, 32276413, 32276415, 32276417, 32276419, 32276421, 32276423, 32276425, 32276427, 32276429, 32276431, 32276433, 32276435, 32276437, 32276439, + 32276441, 32276443, 32276445, 32276447, 32276449, 32276451, 32276453, 32276455, 32276457, 32276459, 32276461, 32276463, 32276465, 32276467, 32276469, + 32276471, 32276473, 32276475, 32276477, 32276479, 0, 32268291, 32268293, 32268295, 32268297, 32268299, 32268301, 32268303, 32268305, 32268307, + 32268309, 32268311, 32268313, 32268315, 32268317, 32268319, 32268321, 32268323, 32268325, 32268327, 32268329, 32268331, 32268333, 32268335, 32268337, + 32268339, 32268341, 32268343, 32268345, 32268347, 32268349, 32268351, 32268353, 32268355, 32268357, 32268359, 32268361, 32268363, 32268365, 32268367, + 32268369, 32268371, 32268373, 32268375, 32268377, 32268379, 32268381, 32268383, 32268385, 32268387, 32268389, 32268391, 32268393, 32268395, 32268397, + 32268399, 32268401, 32268403, 32268405, 32268407, 32268409, 32268411, 32268413, 32268415, 32292737, 32292739, 32292741, 32292743, 32292745, 32292747, + 32292749, 32292751, 32292753, 32292755, 32292757, 32292759, 32292761, 32292763, 32292765, 32292767, 32292769, 32292771, 32292773, 32292775, 32292777, + 32292779, 32292781, 32292783, 32292785, 32292787, 32292789, 32292791, 32292793, 32292795, 32292797, 32292799, 32292801, 32292803, 32292805, 32292807, + 32292809, 32292811, 32292813, 32292815, 32292817, 32292819, 32292821, 32292823, 32292825, 32292827, 32292829, 32292831, 32292833, 32292835, 32292837, + 32292839, 32292841, 32292843, 32292845, 32292847, 32292849, 32292851, 32292853, 32292855, 32292857, 32292859, 32292861, 32292863, 0, 32284675, + 32284677, 32284679, 32284681, 32284683, 32284685, 32284687, 32284689, 32284691, 32284693, 32284695, 32284697, 32284699, 32284701, 32284703, 32284705, + 32284707, 32284709, 32284711, 32284713, 32284715, 32284717, 32284719, 32284721, 32284723, 32284725, 32284727, 32284729, 32284731, 32284733, 32284735, + 32284737, 32284739, 32284741, 32284743, 32284745, 32284747, 32284749, 32284751, 32284753, 32284755, 32284757, 32284759, 32284761, 32284763, 32284765, + 32284767, 32284769, 32284771, 32284773, 32284775, 32284777, 32284779, 32284781, 32284783, 32284785, 32284787, 32284789, 32284791, 32284793, 32284795, + 32284797, 32284799, 32309121, 32309123, 32309125, 32309127, 32309129, 32309131, 32309133, 32309135, 32309137, 32309139, 32309141, 32309143, 32309145, + 32309147, 32309149, 32309151, 32309153, 32309155, 32309157, 32309159, 32309161, 32309163, 32309165, 32309167, 32309169, 32309171, 32309173, 32309175, + 32309177, 32309179, 32309181, 32309183, 32309185, 32309187, 32309189, 32309191, 32309193, 32309195, 32309197, 32309199, 32309201, 32309203, 32309205, + 32309207, 32309209, 32309211, 32309213, 32309215, 32309217, 32309219, 32309221, 32309223, 32309225, 32309227, 32309229, 32309231, 32309233, 32309235, + 32309237, 32309239, 32309241, 32309243, 32309245, 32309247, 0, 32301059, 32301061, 32301063, 32301065, 32301067, 32301069, 32301071, 32301073, + 32301075, 32301077, 32301079, 32301081, 32301083, 32301085, 32301087, 32301089, 32301091, 32301093, 32301095, 32301097, 32301099, 32301101, 32301103, + 32301105, 32301107, 32301109, 32301111, 32301113, 32301115, 32301117, 32301119, 32301121, 32301123, 32301125, 32301127, 32301129, 32301131, 32301133, + 32301135, 32301137, 32301139, 32301141, 32301143, 32301145, 32301147, 32301149, 32301151, 32301153, 32301155, 32301157, 32301159, 32301161, 32301163, + 32301165, 32301167, 32301169, 32301171, 32301173, 32301175, 32301177, 32301179, 32301181, 32301183, 32325505, 32325507, 32325509, 32325511, 32325513, + 32325515, 32325517, 32325519, 32325521, 32325523, 32325525, 32325527, 32325529, 32325531, 32325533, 32325535, 32325537, 32325539, 32325541, 32325543, + 32325545, 32325547, 32325549, 32325551, 32325553, 32325555, 32325557, 32325559, 32325561, 32325563, 32325565, 32325567, 32325569, 32325571, 32325573, + 32325575, 32325577, 32325579, 32325581, 32325583, 32325585, 32325587, 32325589, 32325591, 32325593, 32325595, 32325597, 32325599, 32325601, 32325603, + 32325605, 32325607, 32325609, 32325611, 32325613, 32325615, 32325617, 32325619, 32325621, 32325623, 32325625, 32325627, 32325629, 32325631, 0, + 32317443, 32317445, 32317447, 32317449, 32317451, 32317453, 32317455, 32317457, 32317459, 32317461, 32317463, 32317465, 32317467, 32317469, 32317471, + 32317473, 32317475, 32317477, 32317479, 32317481, 32317483, 32317485, 32317487, 32317489, 32317491, 32317493, 32317495, 32317497, 32317499, 32317501, + 32317503, 32317505, 32317507, 32317509, 32317511, 32317513, 32317515, 32317517, 32317519, 32317521, 32317523, 32317525, 32317527, 32317529, 32317531, + 32317533, 32317535, 32317537, 32317539, 32317541, 32317543, 32317545, 32317547, 32317549, 32317551, 32317553, 32317555, 32317557, 32317559, 32317561, + 32317563, 32317565, 32317567, 32341889, 32341891, 32341893, 32341895, 32341897, 32341899, 32341901, 32341903, 32341905, 32341907, 32341909, 32341911, + 32341913, 32341915, 32341917, 32341919, 32341921, 32341923, 32341925, 32341927, 32341929, 32341931, 32341933, 32341935, 32341937, 32341939, 32341941, + 32341943, 32341945, 32341947, 32341949, 32341951, 32341953, 32341955, 32341957, 32341959, 32341961, 32341963, 32341965, 32341967, 32341969, 32341971, + 32341973, 32341975, 32341977, 32341979, 32341981, 32341983, 32341985, 32341987, 32341989, 32341991, 32341993, 32341995, 32341997, 32341999, 32342001, + 32342003, 32342005, 32342007, 32342009, 32342011, 32342013, 32342015, 0, 32333827, 32333829, 32333831, 32333833, 32333835, 32333837, 32333839, + 32333841, 32333843, 32333845, 32333847, 32333849, 32333851, 32333853, 32333855, 32333857, 32333859, 32333861, 32333863, 32333865, 32333867, 32333869, + 32333871, 32333873, 32333875, 32333877, 32333879, 32333881, 32333883, 32333885, 32333887, 32333889, 32333891, 32333893, 32333895, 32333897, 32333899, + 32333901, 32333903, 32333905, 32333907, 32333909, 32333911, 32333913, 32333915, 32333917, 32333919, 32333921, 32333923, 32333925, 32333927, 32333929, + 32333931, 32333933, 32333935, 32333937, 32333939, 32333941, 32333943, 32333945, 32333947, 32333949, 32333951, 32358273, 32358275, 32358277, 32358279, + 32358281, 32358283, 32358285, 32358287, 32358289, 32358291, 32358293, 32358295, 32358297, 32358299, 32358301, 32358303, 32358305, 32358307, 32358309, + 32358311, 32358313, 32358315, 32358317, 32358319, 32358321, 32358323, 32358325, 32358327, 32358329, 32358331, 32358333, 32358335, 32358337, 32358339, + 32358341, 32358343, 32358345, 32358347, 32358349, 32358351, 32358353, 32358355, 32358357, 32358359, 32358361, 32358363, 32358365, 32358367, 32358369, + 32358371, 32358373, 32358375, 32358377, 32358379, 32358381, 32358383, 32358385, 32358387, 32358389, 32358391, 32358393, 32358395, 32358397, 32358399, + 0, 32350211, 32350213, 32350215, 32350217, 32350219, 32350221, 32350223, 32350225, 32350227, 32350229, 32350231, 32350233, 32350235, 32350237, + 32350239, 32350241, 32350243, 32350245, 32350247, 32350249, 32350251, 32350253, 32350255, 32350257, 32350259, 32350261, 32350263, 32350265, 32350267, + 32350269, 32350271, 32350273, 32350275, 32350277, 32350279, 32350281, 32350283, 32350285, 32350287, 32350289, 32350291, 32350293, 32350295, 32350297, + 32350299, 32350301, 32350303, 32350305, 32350307, 32350309, 32350311, 32350313, 32350315, 32350317, 32350319, 32350321, 32350323, 32350325, 32350327, + 32350329, 32350331, 32350333, 32350335, 32374657, 32374659, 32374661, 32374663, 32374665, 32374667, 32374669, 32374671, 32374673, 32374675, 32374677, + 32374679, 32374681, 32374683, 32374685, 32374687, 32374689, 32374691, 32374693, 32374695, 32374697, 32374699, 32374701, 32374703, 32374705, 32374707, + 32374709, 32374711, 32374713, 32374715, 32374717, 32374719, 32374721, 32374723, 32374725, 32374727, 32374729, 32374731, 32374733, 32374735, 32374737, + 32374739, 32374741, 32374743, 32374745, 32374747, 32374749, 32374751, 32374753, 32374755, 32374757, 32374759, 32374761, 32374763, 32374765, 32374767, + 32374769, 32374771, 32374773, 32374775, 32374777, 32374779, 32374781, 32374783, 0, 32366595, 32366597, 32366599, 32366601, 32366603, 32366605, + 32366607, 32366609, 32366611, 32366613, 32366615, 32366617, 32366619, 32366621, 32366623, 32366625, 32366627, 32366629, 32366631, 32366633, 32366635, + 32366637, 32366639, 32366641, 32366643, 32366645, 32366647, 32366649, 32366651, 32366653, 32366655, 32366657, 32366659, 32366661, 32366663, 32366665, + 32366667, 32366669, 32366671, 32366673, 32366675, 32366677, 32366679, 32366681, 32366683, 32366685, 32366687, 32366689, 32366691, 32366693, 32366695, + 32366697, 32366699, 32366701, 32366703, 32366705, 32366707, 32366709, 32366711, 32366713, 32366715, 32366717, 32366719, 32391041, 32391043, 32391045, + 32391047, 32391049, 32391051, 32391053, 32391055, 32391057, 32391059, 32391061, 32391063, 32391065, 32391067, 32391069, 32391071, 32391073, 32391075, + 32391077, 32391079, 32391081, 32391083, 32391085, 32391087, 32391089, 32391091, 32391093, 32391095, 32391097, 32391099, 32391101, 32391103, 32391105, + 32391107, 32391109, 32391111, 32391113, 32391115, 32391117, 32391119, 32391121, 32391123, 32391125, 32391127, 32391129, 32391131, 32391133, 32391135, + 32391137, 32391139, 32391141, 32391143, 32391145, 32391147, 32391149, 32391151, 32391153, 32391155, 32391157, 32391159, 32391161, 32391163, 32391165, + 32391167, 0, 32382979, 32382981, 32382983, 32382985, 32382987, 32382989, 32382991, 32382993, 32382995, 32382997, 32382999, 32383001, 32383003, + 32383005, 32383007, 32383009, 32383011, 32383013, 32383015, 32383017, 32383019, 32383021, 32383023, 32383025, 32383027, 32383029, 32383031, 32383033, + 32383035, 32383037, 32383039, 32383041, 32383043, 32383045, 32383047, 32383049, 32383051, 32383053, 32383055, 32383057, 32383059, 32383061, 32383063, + 32383065, 32383067, 32383069, 32383071, 32383073, 32383075, 32383077, 32383079, 32383081, 32383083, 32383085, 32383087, 32383089, 32383091, 32383093, + 32383095, 32383097, 32383099, 32383101, 32383103, 32407425, 32407427, 32407429, 32407431, 32407433, 32407435, 32407437, 32407439, 32407441, 32407443, + 32407445, 32407447, 32407449, 32407451, 32407453, 32407455, 32407457, 32407459, 32407461, 32407463, 32407465, 32407467, 32407469, 32407471, 32407473, + 32407475, 32407477, 32407479, 32407481, 32407483, 32407485, 32407487, 32407489, 32407491, 32407493, 32407495, 32407497, 32407499, 32407501, 32407503, + 32407505, 32407507, 32407509, 32407511, 32407513, 32407515, 32407517, 32407519, 32407521, 32407523, 32407525, 32407527, 32407529, 32407531, 32407533, + 32407535, 32407537, 32407539, 32407541, 32407543, 32407545, 32407547, 32407549, 32407551, 0, 32399363, 32399365, 32399367, 32399369, 32399371, + 32399373, 32399375, 32399377, 32399379, 32399381, 32399383, 32399385, 32399387, 32399389, 32399391, 32399393, 32399395, 32399397, 32399399, 32399401, + 32399403, 32399405, 32399407, 32399409, 32399411, 32399413, 32399415, 32399417, 32399419, 32399421, 32399423, 32399425, 32399427, 32399429, 32399431, + 32399433, 32399435, 32399437, 32399439, 32399441, 32399443, 32399445, 32399447, 32399449, 32399451, 32399453, 32399455, 32399457, 32399459, 32399461, + 32399463, 32399465, 32399467, 32399469, 32399471, 32399473, 32399475, 32399477, 32399479, 32399481, 32399483, 32399485, 32399487, 32423809, 32423811, + 32423813, 32423815, 32423817, 32423819, 32423821, 32423823, 32423825, 32423827, 32423829, 32423831, 32423833, 32423835, 32423837, 32423839, 32423841, + 32423843, 32423845, 32423847, 32423849, 32423851, 32423853, 32423855, 32423857, 32423859, 32423861, 32423863, 32423865, 32423867, 32423869, 32423871, + 32423873, 32423875, 32423877, 32423879, 32423881, 32423883, 32423885, 32423887, 32423889, 32423891, 32423893, 32423895, 32423897, 32423899, 32423901, + 32423903, 32423905, 32423907, 32423909, 32423911, 32423913, 32423915, 32423917, 32423919, 32423921, 32423923, 32423925, 32423927, 32423929, 32423931, + 32423933, 32423935, 0, 32415747, 32415749, 32415751, 32415753, 32415755, 32415757, 32415759, 32415761, 32415763, 32415765, 32415767, 32415769, + 32415771, 32415773, 32415775, 32415777, 32415779, 32415781, 32415783, 32415785, 32415787, 32415789, 32415791, 32415793, 32415795, 32415797, 32415799, + 32415801, 32415803, 32415805, 32415807, 32415809, 32415811, 32415813, 32415815, 32415817, 32415819, 32415821, 32415823, 32415825, 32415827, 32415829, + 32415831, 32415833, 32415835, 32415837, 32415839, 32415841, 32415843, 32415845, 32415847, 32415849, 32415851, 32415853, 32415855, 32415857, 32415859, + 32415861, 32415863, 32415865, 32415867, 32415869, 32415871, 32440193, 32440195, 32440197, 32440199, 32440201, 32440203, 32440205, 32440207, 32440209, + 32440211, 32440213, 32440215, 32440217, 32440219, 32440221, 32440223, 32440225, 32440227, 32440229, 32440231, 32440233, 32440235, 32440237, 32440239, + 32440241, 32440243, 32440245, 32440247, 32440249, 32440251, 32440253, 32440255, 32440257, 32440259, 32440261, 32440263, 32440265, 32440267, 32440269, + 32440271, 32440273, 32440275, 32440277, 32440279, 32440281, 32440283, 32440285, 32440287, 32440289, 32440291, 32440293, 32440295, 32440297, 32440299, + 32440301, 32440303, 32440305, 32440307, 32440309, 32440311, 32440313, 32440315, 32440317, 32440319, 0, 32432131, 32432133, 32432135, 32432137, + 32432139, 32432141, 32432143, 32432145, 32432147, 32432149, 32432151, 32432153, 32432155, 32432157, 32432159, 32432161, 32432163, 32432165, 32432167, + 32432169, 32432171, 32432173, 32432175, 32432177, 32432179, 32432181, 32432183, 32432185, 32432187, 32432189, 32432191, 32432193, 32432195, 32432197, + 32432199, 32432201, 32432203, 32432205, 32432207, 32432209, 32432211, 32432213, 32432215, 32432217, 32432219, 32432221, 32432223, 32432225, 32432227, + 32432229, 32432231, 32432233, 32432235, 32432237, 32432239, 32432241, 32432243, 32432245, 32432247, 32432249, 32432251, 32432253, 32432255, 32456577, + 32456579, 32456581, 32456583, 32456585, 32456587, 32456589, 32456591, 32456593, 32456595, 32456597, 32456599, 32456601, 32456603, 32456605, 32456607, + 32456609, 32456611, 32456613, 32456615, 32456617, 32456619, 32456621, 32456623, 32456625, 32456627, 32456629, 32456631, 32456633, 32456635, 32456637, + 32456639, 32456641, 32456643, 32456645, 32456647, 32456649, 32456651, 32456653, 32456655, 32456657, 32456659, 32456661, 32456663, 32456665, 32456667, + 32456669, 32456671, 32456673, 32456675, 32456677, 32456679, 32456681, 32456683, 32456685, 32456687, 32456689, 32456691, 32456693, 32456695, 32456697, + 32456699, 32456701, 32456703, 0, 32448515, 32448517, 32448519, 32448521, 32448523, 32448525, 32448527, 32448529, 32448531, 32448533, 32448535, + 32448537, 32448539, 32448541, 32448543, 32448545, 32448547, 32448549, 32448551, 32448553, 32448555, 32448557, 32448559, 32448561, 32448563, 32448565, + 32448567, 32448569, 32448571, 32448573, 32448575, 32448577, 32448579, 32448581, 32448583, 32448585, 32448587, 32448589, 32448591, 32448593, 32448595, + 32448597, 32448599, 32448601, 32448603, 32448605, 32448607, 32448609, 32448611, 32448613, 32448615, 32448617, 32448619, 32448621, 32448623, 32448625, + 32448627, 32448629, 32448631, 32448633, 32448635, 32448637, 32448639, 32472961, 32472963, 32472965, 32472967, 32472969, 32472971, 32472973, 32472975, + 32472977, 32472979, 32472981, 32472983, 32472985, 32472987, 32472989, 32472991, 32472993, 32472995, 32472997, 32472999, 32473001, 32473003, 32473005, + 32473007, 32473009, 32473011, 32473013, 32473015, 32473017, 32473019, 32473021, 32473023, 32473025, 32473027, 32473029, 32473031, 32473033, 32473035, + 32473037, 32473039, 32473041, 32473043, 32473045, 32473047, 32473049, 32473051, 32473053, 32473055, 32473057, 32473059, 32473061, 32473063, 32473065, + 32473067, 32473069, 32473071, 32473073, 32473075, 32473077, 32473079, 32473081, 32473083, 32473085, 32473087, 0, 32464899, 32464901, 32464903, + 32464905, 32464907, 32464909, 32464911, 32464913, 32464915, 32464917, 32464919, 32464921, 32464923, 32464925, 32464927, 32464929, 32464931, 32464933, + 32464935, 32464937, 32464939, 32464941, 32464943, 32464945, 32464947, 32464949, 32464951, 32464953, 32464955, 32464957, 32464959, 32464961, 32464963, + 32464965, 32464967, 32464969, 32464971, 32464973, 32464975, 32464977, 32464979, 32464981, 32464983, 32464985, 32464987, 32464989, 32464991, 32464993, + 32464995, 32464997, 32464999, 32465001, 32465003, 32465005, 32465007, 32465009, 32465011, 32465013, 32465015, 32465017, 32465019, 32465021, 32465023, + 32489345, 32489347, 32489349, 32489351, 32489353, 32489355, 32489357, 32489359, 32489361, 32489363, 32489365, 32489367, 32489369, 32489371, 32489373, + 32489375, 32489377, 32489379, 32489381, 32489383, 32489385, 32489387, 32489389, 32489391, 32489393, 32489395, 32489397, 32489399, 32489401, 32489403, + 32489405, 32489407, 32489409, 32489411, 32489413, 32489415, 32489417, 32489419, 32489421, 32489423, 32489425, 32489427, 32489429, 32489431, 32489433, + 32489435, 32489437, 32489439, 32489441, 32489443, 32489445, 32489447, 32489449, 32489451, 32489453, 32489455, 32489457, 32489459, 32489461, 32489463, + 32489465, 32489467, 32489469, 32489471, 0, 32481283, 32481285, 32481287, 32481289, 32481291, 32481293, 32481295, 32481297, 32481299, 32481301, + 32481303, 32481305, 32481307, 32481309, 32481311, 32481313, 32481315, 32481317, 32481319, 32481321, 32481323, 32481325, 32481327, 32481329, 32481331, + 32481333, 32481335, 32481337, 32481339, 32481341, 32481343, 32481345, 32481347, 32481349, 32481351, 32481353, 32481355, 32481357, 32481359, 32481361, + 32481363, 32481365, 32481367, 32481369, 32481371, 32481373, 32481375, 32481377, 32481379, 32481381, 32481383, 32481385, 32481387, 32481389, 32481391, + 32481393, 32481395, 32481397, 32481399, 32481401, 32481403, 32481405, 32481407, 32505729, 32505731, 32505733, 32505735, 32505737, 32505739, 32505741, + 32505743, 32505745, 32505747, 32505749, 32505751, 32505753, 32505755, 32505757, 32505759, 32505761, 32505763, 32505765, 32505767, 32505769, 32505771, + 32505773, 32505775, 32505777, 32505779, 32505781, 32505783, 32505785, 32505787, 32505789, 32505791, 32505793, 32505795, 32505797, 32505799, 32505801, + 32505803, 32505805, 32505807, 32505809, 32505811, 32505813, 32505815, 32505817, 32505819, 32505821, 32505823, 32505825, 32505827, 32505829, 32505831, + 32505833, 32505835, 32505837, 32505839, 32505841, 32505843, 32505845, 32505847, 32505849, 32505851, 32505853, 32505855, 0, 32497667, 32497669, + 32497671, 32497673, 32497675, 32497677, 32497679, 32497681, 32497683, 32497685, 32497687, 32497689, 32497691, 32497693, 32497695, 32497697, 32497699, + 32497701, 32497703, 32497705, 32497707, 32497709, 32497711, 32497713, 32497715, 32497717, 32497719, 32497721, 32497723, 32497725, 32497727, 32497729, + 32497731, 32497733, 32497735, 32497737, 32497739, 32497741, 32497743, 32497745, 32497747, 32497749, 32497751, 32497753, 32497755, 32497757, 32497759, + 32497761, 32497763, 32497765, 32497767, 32497769, 32497771, 32497773, 32497775, 32497777, 32497779, 32497781, 32497783, 32497785, 32497787, 32497789, + 32497791, 32522113, 32522115, 32522117, 32522119, 32522121, 32522123, 32522125, 32522127, 32522129, 32522131, 32522133, 32522135, 32522137, 32522139, + 32522141, 32522143, 32522145, 32522147, 32522149, 32522151, 32522153, 32522155, 32522157, 32522159, 32522161, 32522163, 32522165, 32522167, 32522169, + 32522171, 32522173, 32522175, 32522177, 32522179, 32522181, 32522183, 32522185, 32522187, 32522189, 32522191, 32522193, 32522195, 32522197, 32522199, + 32522201, 32522203, 32522205, 32522207, 49331, 24585, 24587, 12301, 6191, 3117, 793, 207, 179, 9, 11, + 13, 47, 45, 25, 15, 0, 14, 24, 44, 46, 12, 10, 8, 178, 206, + 792, 3116, 6190, 12300, 24586, 24584, 49330, 32514083, 32514085, 32514087, 32514089, 32514091, 32514093, 32514095, 32514097, + 32514099, 32514101, 32514103, 32514105, 32514107, 32514109, 32514111, 32514113, 32514115, 32514117, 32514119, 32514121, 32514123, 32514125, 32514127, + 32514129, 32514131, 32514133, 32514135, 32514137, 32514139, 32514141, 32514143, 32514145, 32514147, 32514149, 32514151, 32514153, 32514155, 32514157, + 32514159, 32514161, 32514163, 32514165, 32514167, 32514169, 32514171, 32514173, 32514175, 32538497, 32538499, 32538501, 32538503, 32538505, 32538507, + 32538509, 32538511, 32538513, 32538515, 32538517, 32538519, 32538521, 32538523, 32538525, 32538527, 32538529, 32538531, 32538533, 32538535, 32538537, + 32538539, 32538541, 32538543, 32538545, 32538547, 32538549, 32538551, 32538553, 32538555, 32538557, 32538559, 32538561, 32538563, 32538565, 32538567, + 32538569, 32538571, 32538573, 32538575, 32538577, 32538579, 32538581, 32538583, 32538585, 32538587, 32538589, 32538591, 32538593, 32538595, 32538597, + 32538599, 32538601, 32538603, 32538605, 32538607, 114867, 57353, 12299, 6189, 799, 11, 45, 31, 0, 30, + 44, 10, 798, 6188, 12298, 57352, 114866, 32530451, 32530453, 32530455, 32530457, 32530459, 32530461, 32530463, 32530465, + 32530467, 32530469, 32530471, 32530473, 32530475, 32530477, 32530479, 32530481, 32530483, 32530485, 32530487, 32530489, 32530491, 32530493, 32530495, + 32530497, 32530499, 32530501, 32530503, 32530505, 32530507, 32530509, 32530511, 32530513, 32530515, 32530517, 32530519, 32530521, 32530523, 32530525, + 32530527, 32530529, 32530531, 32530533, 32530535, 32530537, 32530539, 32530541, 32530543, 32530545, 32530547, 32530549, 32530551, 32530553, 32530555, + 32530557, 32530559, 32554881, 32554883, 32554885, 32554887, 32554889, 32554891, 32554893, 32554895, 32554897, 32554899, 32554901, 32554903, 32554905, + 32554907, 32554909, 32554911, 32554913, 32554915, 32554917, 32554919, 32554921, 32554923, 32554925, 32554927, 32554929, 32554931, 32554933, 32554935, + 32554937, 32554939, 32554941, 32554943, 32554945, 32554947, 32554949, 32554951, 32554953, 32554955, 32554957, 32554959, 32554961, 32554963, 32554965, + 32554967, 32554969, 32554971, 32554973, 32554975, 32554977, 32554979, 32554981, 32554983, 32554985, 32554987, 32554989, 32554991, 32554993, 32554995, + 32554997, 32554999, 12297, 797, 9, 29, 0, 28, 8, 796, 12296, 32546827, 32546829, 32546831, 32546833, + 32546835, 32546837, 32546839, 32546841, 32546843, 32546845, 32546847, 32546849, 32546851, 32546853, 32546855, 32546857, 32546859, 32546861, 32546863, + 32546865, 32546867, 32546869, 32546871, 32546873, 32546875, 32546877, 32546879, 32546881, 32546883, 32546885, 32546887, 32546889, 32546891, 32546893, + 32546895, 32546897, 32546899, 32546901, 32546903, 32546905, 32546907, 32546909, 32546911, 32546913, 32546915, 32546917, 32546919, 32546921, 32546923, + 32546925, 32546927, 32546929, 32546931, 32546933, 32546935, 32546937, 32546939, 32546941, 32546943, 32571265, 32571267, 32571269, 32571271, 32571273, + 32571275, 32571277, 32571279, 32571281, 32571283, 32571285, 32571287, 32571289, 32571291, 32571293, 32571295, 32571297, 32571299, 32571301, 32571303, + 32571305, 32571307, 32571309, 32571311, 32571313, 32571315, 32571317, 32571319, 32571321, 32571323, 32571325, 32571327, 32571329, 32571331, 32571333, + 32571335, 32571337, 32571339, 32571341, 32571343, 32571345, 32571347, 32571349, 32571351, 32571353, 32571355, 32571357, 32571359, 32571361, 32571363, + 32571365, 32571367, 32571369, 32571371, 32571373, 32571375, 32571377, 32571379, 32571381, 32571383, 24649, 1571, 73, 35, 0, + 34, 72, 1570, 24648, 32563211, 32563213, 32563215, 32563217, 32563219, 32563221, 32563223, 32563225, 32563227, 32563229, 32563231, + 32563233, 32563235, 32563237, 32563239, 32563241, 32563243, 32563245, 32563247, 32563249, 32563251, 32563253, 32563255, 32563257, 32563259, 32563261, + 32563263, 32563265, 32563267, 32563269, 32563271, 32563273, 32563275, 32563277, 32563279, 32563281, 32563283, 32563285, 32563287, 32563289, 32563291, + 32563293, 32563295, 32563297, 32563299, 32563301, 32563303, 32563305, 32563307, 32563309, 32563311, 32563313, 32563315, 32563317, 32563319, 32563321, + 32563323, 32563325, 32563327, 32587649, 32587651, 32587653, 32587655, 32587657, 32587659, 32587661, 32587663, 32587665, 32587667, 32587669, 32587671, + 32587673, 32587675, 32587677, 32587679, 32587681, 32587683, 32587685, 32587687, 32587689, 32587691, 32587693, 32587695, 32587697, 32587699, 32587701, + 32587703, 32587705, 32587707, 32587709, 32587711, 32587713, 32587715, 32587717, 32587719, 32587721, 32587723, 32587725, 32587727, 32587729, 32587731, + 32587733, 32587735, 32587737, 32587739, 32587741, 32587743, 32587745, 32587747, 32587749, 32587751, 32587753, 32587755, 32587757, 32587759, 32587761, + 32587763, 32587765, 32587767, 24651, 1569, 75, 33, 0, 32, 74, 1568, 24650, 32579595, 32579597, 32579599, + 32579601, 32579603, 32579605, 32579607, 32579609, 32579611, 32579613, 32579615, 32579617, 32579619, 32579621, 32579623, 32579625, 32579627, 32579629, + 32579631, 32579633, 32579635, 32579637, 32579639, 32579641, 32579643, 32579645, 32579647, 32579649, 32579651, 32579653, 32579655, 32579657, 32579659, + 32579661, 32579663, 32579665, 32579667, 32579669, 32579671, 32579673, 32579675, 32579677, 32579679, 32579681, 32579683, 32579685, 32579687, 32579689, + 32579691, 32579693, 32579695, 32579697, 32579699, 32579701, 32579703, 32579705, 32579707, 32579709, 32579711, 32604033, 32604035, 32604037, 32604039, + 32604041, 32604043, 32604045, 32604047, 32604049, 32604051, 32604053, 32604055, 32604057, 32604059, 32604061, 32604063, 32604065, 32604067, 32604069, + 32604071, 32604073, 32604075, 32604077, 32604079, 32604081, 32604083, 32604085, 32604087, 32604089, 32604091, 32604093, 32604095, 32604097, 32604099, + 32604101, 32604103, 32604105, 32604107, 32604109, 32604111, 32604113, 32604115, 32604117, 32604119, 32604121, 32604123, 32604125, 32604127, 32604129, + 32604131, 32604133, 32604135, 32604137, 32604139, 32604141, 32604143, 32604145, 32604147, 32604149, 32604151, 49333, 1575, 181, 39, + 0, 38, 180, 1574, 49332, 32595979, 32595981, 32595983, 32595985, 32595987, 32595989, 32595991, 32595993, 32595995, 32595997, + 32595999, 32596001, 32596003, 32596005, 32596007, 32596009, 32596011, 32596013, 32596015, 32596017, 32596019, 32596021, 32596023, 32596025, 32596027, + 32596029, 32596031, 32596033, 32596035, 32596037, 32596039, 32596041, 32596043, 32596045, 32596047, 32596049, 32596051, 32596053, 32596055, 32596057, + 32596059, 32596061, 32596063, 32596065, 32596067, 32596069, 32596071, 32596073, 32596075, 32596077, 32596079, 32596081, 32596083, 32596085, 32596087, + 32596089, 32596091, 32596093, 32596095, 32620417, 32620419, 32620421, 32620423, 32620425, 32620427, 32620429, 32620431, 32620433, 32620435, 32620437, + 32620439, 32620441, 32620443, 32620445, 32620447, 32620449, 32620451, 32620453, 32620455, 32620457, 32620459, 32620461, 32620463, 32620465, 32620467, + 32620469, 32620471, 32620473, 32620475, 32620477, 32620479, 32620481, 32620483, 32620485, 32620487, 32620489, 32620491, 32620493, 32620495, 32620497, + 32620499, 32620501, 32620503, 32620505, 32620507, 32620509, 32620511, 32620513, 32620515, 32620517, 32620519, 32620521, 32620523, 32620525, 32620527, + 32620529, 32620531, 32620533, 32620535, 49335, 3115, 183, 43, 0, 42, 182, 3114, 49334, 32612363, 32612365, + 32612367, 32612369, 32612371, 32612373, 32612375, 32612377, 32612379, 32612381, 32612383, 32612385, 32612387, 32612389, 32612391, 32612393, 32612395, + 32612397, 32612399, 32612401, 32612403, 32612405, 32612407, 32612409, 32612411, 32612413, 32612415, 32612417, 32612419, 32612421, 32612423, 32612425, + 32612427, 32612429, 32612431, 32612433, 32612435, 32612437, 32612439, 32612441, 32612443, 32612445, 32612447, 32612449, 32612451, 32612453, 32612455, + 32612457, 32612459, 32612461, 32612463, 32612465, 32612467, 32612469, 32612471, 32612473, 32612475, 32612477, 32612479, 32636801, 32636803, 32636805, + 32636807, 32636809, 32636811, 32636813, 32636815, 32636817, 32636819, 32636821, 32636823, 32636825, 32636827, 32636829, 32636831, 32636833, 32636835, + 32636837, 32636839, 32636841, 32636843, 32636845, 32636847, 32636849, 32636851, 32636853, 32636855, 32636857, 32636859, 32636861, 32636863, 32636865, + 32636867, 32636869, 32636871, 32636873, 32636875, 32636877, 32636879, 32636881, 32636883, 32636885, 32636887, 32636889, 32636891, 32636893, 32636895, + 32636897, 32636899, 32636901, 32636903, 32636905, 32636907, 32636909, 32636911, 32636913, 32636915, 32636917, 32636919, 32636921, 32636923, 1817, + 41, 0, 40, 1816, 32628743, 32628745, 32628747, 32628749, 32628751, 32628753, 32628755, 32628757, 32628759, 32628761, 32628763, + 32628765, 32628767, 32628769, 32628771, 32628773, 32628775, 32628777, 32628779, 32628781, 32628783, 32628785, 32628787, 32628789, 32628791, 32628793, + 32628795, 32628797, 32628799, 32628801, 32628803, 32628805, 32628807, 32628809, 32628811, 32628813, 32628815, 32628817, 32628819, 32628821, 32628823, + 32628825, 32628827, 32628829, 32628831, 32628833, 32628835, 32628837, 32628839, 32628841, 32628843, 32628845, 32628847, 32628849, 32628851, 32628853, + 32628855, 32628857, 32628859, 32628861, 32628863, 32653185, 32653187, 32653189, 32653191, 32653193, 32653195, 32653197, 32653199, 32653201, 32653203, + 32653205, 32653207, 32653209, 32653211, 32653213, 32653215, 32653217, 32653219, 32653221, 32653223, 32653225, 32653227, 32653229, 32653231, 32653233, + 32653235, 32653237, 32653239, 32653241, 32653243, 32653245, 32653247, 32653249, 32653251, 32653253, 32653255, 32653257, 32653259, 32653261, 32653263, + 32653265, 32653267, 32653269, 32653271, 32653273, 32653275, 32653277, 32653279, 32653281, 32653283, 32653285, 32653287, 32653289, 32653291, 32653293, + 32653295, 32653297, 32653299, 32653301, 32653303, 32653305, 32653307, 3111, 39, 0, 38, 3110, 32645127, 32645129, 32645131, + 32645133, 32645135, 32645137, 32645139, 32645141, 32645143, 32645145, 32645147, 32645149, 32645151, 32645153, 32645155, 32645157, 32645159, 32645161, + 32645163, 32645165, 32645167, 32645169, 32645171, 32645173, 32645175, 32645177, 32645179, 32645181, 32645183, 32645185, 32645187, 32645189, 32645191, + 32645193, 32645195, 32645197, 32645199, 32645201, 32645203, 32645205, 32645207, 32645209, 32645211, 32645213, 32645215, 32645217, 32645219, 32645221, + 32645223, 32645225, 32645227, 32645229, 32645231, 32645233, 32645235, 32645237, 32645239, 32645241, 32645243, 32645245, 32645247, 32669569, 32669571, + 32669573, 32669575, 32669577, 32669579, 32669581, 32669583, 32669585, 32669587, 32669589, 32669591, 32669593, 32669595, 32669597, 32669599, 32669601, + 32669603, 32669605, 32669607, 32669609, 32669611, 32669613, 32669615, 32669617, 32669619, 32669621, 32669623, 32669625, 32669627, 32669629, 32669631, + 32669633, 32669635, 32669637, 32669639, 32669641, 32669643, 32669645, 32669647, 32669649, 32669651, 32669653, 32669655, 32669657, 32669659, 32669661, + 32669663, 32669665, 32669667, 32669669, 32669671, 32669673, 32669675, 32669677, 32669679, 32669681, 32669683, 32669685, 32669687, 32669689, 32669691, + 3125, 53, 0, 52, 3124, 32661511, 32661513, 32661515, 32661517, 32661519, 32661521, 32661523, 32661525, 32661527, 32661529, + 32661531, 32661533, 32661535, 32661537, 32661539, 32661541, 32661543, 32661545, 32661547, 32661549, 32661551, 32661553, 32661555, 32661557, 32661559, + 32661561, 32661563, 32661565, 32661567, 32661569, 32661571, 32661573, 32661575, 32661577, 32661579, 32661581, 32661583, 32661585, 32661587, 32661589, + 32661591, 32661593, 32661595, 32661597, 32661599, 32661601, 32661603, 32661605, 32661607, 32661609, 32661611, 32661613, 32661615, 32661617, 32661619, + 32661621, 32661623, 32661625, 32661627, 32661629, 32661631, 32685953, 32685955, 32685957, 32685959, 32685961, 32685963, 32685965, 32685967, 32685969, + 32685971, 32685973, 32685975, 32685977, 32685979, 32685981, 32685983, 32685985, 32685987, 32685989, 32685991, 32685993, 32685995, 32685997, 32685999, + 32686001, 32686003, 32686005, 32686007, 32686009, 32686011, 32686013, 32686015, 32686017, 32686019, 32686021, 32686023, 32686025, 32686027, 32686029, + 32686031, 32686033, 32686035, 32686037, 32686039, 32686041, 32686043, 32686045, 32686047, 32686049, 32686051, 32686053, 32686055, 32686057, 32686059, + 32686061, 32686063, 32686065, 32686067, 32686069, 32686071, 32686073, 32686075, 6187, 43, 0, 42, 6186, 32677895, 32677897, + 32677899, 32677901, 32677903, 32677905, 32677907, 32677909, 32677911, 32677913, 32677915, 32677917, 32677919, 32677921, 32677923, 32677925, 32677927, + 32677929, 32677931, 32677933, 32677935, 32677937, 32677939, 32677941, 32677943, 32677945, 32677947, 32677949, 32677951, 32677953, 32677955, 32677957, + 32677959, 32677961, 32677963, 32677965, 32677967, 32677969, 32677971, 32677973, 32677975, 32677977, 32677979, 32677981, 32677983, 32677985, 32677987, + 32677989, 32677991, 32677993, 32677995, 32677997, 32677999, 32678001, 32678003, 32678005, 32678007, 32678009, 32678011, 32678013, 32678015, 32702337, + 32702339, 32702341, 32702343, 32702345, 32702347, 32702349, 32702351, 32702353, 32702355, 32702357, 32702359, 32702361, 32702363, 32702365, 32702367, + 32702369, 32702371, 32702373, 32702375, 32702377, 32702379, 32702381, 32702383, 32702385, 32702387, 32702389, 32702391, 32702393, 32702395, 32702397, + 32702399, 32702401, 32702403, 32702405, 32702407, 32702409, 32702411, 32702413, 32702415, 32702417, 32702419, 32702421, 32702423, 32702425, 32702427, + 32702429, 32702431, 32702433, 32702435, 32702437, 32702439, 32702441, 32702443, 32702445, 32702447, 32702449, 32702451, 32702453, 32702455, 32702457, + 32702459, 6185, 41, 0, 40, 6184, 32694279, 32694281, 32694283, 32694285, 32694287, 32694289, 32694291, 32694293, 32694295, + 32694297, 32694299, 32694301, 32694303, 32694305, 32694307, 32694309, 32694311, 32694313, 32694315, 32694317, 32694319, 32694321, 32694323, 32694325, + 32694327, 32694329, 32694331, 32694333, 32694335, 32694337, 32694339, 32694341, 32694343, 32694345, 32694347, 32694349, 32694351, 32694353, 32694355, + 32694357, 32694359, 32694361, 32694363, 32694365, 32694367, 32694369, 32694371, 32694373, 32694375, 32694377, 32694379, 32694381, 32694383, 32694385, + 32694387, 32694389, 32694391, 32694393, 32694395, 32694397, 32694399, 32718721, 32718723, 32718725, 32718727, 32718729, 32718731, 32718733, 32718735, + 32718737, 32718739, 32718741, 32718743, 32718745, 32718747, 32718749, 32718751, 32718753, 32718755, 32718757, 32718759, 32718761, 32718763, 32718765, + 32718767, 32718769, 32718771, 32718773, 32718775, 32718777, 32718779, 32718781, 32718783, 32718785, 32718787, 32718789, 32718791, 32718793, 32718795, + 32718797, 32718799, 32718801, 32718803, 32718805, 32718807, 32718809, 32718811, 32718813, 32718815, 32718817, 32718819, 32718821, 32718823, 32718825, + 32718827, 32718829, 32718831, 32718833, 32718835, 32718837, 32718839, 32718841, 32718843, 6183, 39, 0, 38, 6182, 32710663, + 32710665, 32710667, 32710669, 32710671, 32710673, 32710675, 32710677, 32710679, 32710681, 32710683, 32710685, 32710687, 32710689, 32710691, 32710693, + 32710695, 32710697, 32710699, 32710701, 32710703, 32710705, 32710707, 32710709, 32710711, 32710713, 32710715, 32710717, 32710719, 32710721, 32710723, + 32710725, 32710727, 32710729, 32710731, 32710733, 32710735, 32710737, 32710739, 32710741, 32710743, 32710745, 32710747, 32710749, 32710751, 32710753, + 32710755, 32710757, 32710759, 32710761, 32710763, 32710765, 32710767, 32710769, 32710771, 32710773, 32710775, 32710777, 32710779, 32710781, 32710783, + 32735105, 32735107, 32735109, 32735111, 32735113, 32735115, 32735117, 32735119, 32735121, 32735123, 32735125, 32735127, 32735129, 32735131, 32735133, + 32735135, 32735137, 32735139, 32735141, 32735143, 32735145, 32735147, 32735149, 32735151, 32735153, 32735155, 32735157, 32735159, 32735161, 32735163, + 32735165, 32735167, 32735169, 32735171, 32735173, 32735175, 32735177, 32735179, 32735181, 32735183, 32735185, 32735187, 32735189, 32735191, 32735193, + 32735195, 32735197, 32735199, 32735201, 32735203, 32735205, 32735207, 32735209, 32735211, 32735213, 32735215, 32735217, 32735219, 32735221, 32735223, + 32735225, 32735227, 6181, 37, 0, 36, 6180, 32727047, 32727049, 32727051, 32727053, 32727055, 32727057, 32727059, 32727061, + 32727063, 32727065, 32727067, 32727069, 32727071, 32727073, 32727075, 32727077, 32727079, 32727081, 32727083, 32727085, 32727087, 32727089, 32727091, + 32727093, 32727095, 32727097, 32727099, 32727101, 32727103, 32727105, 32727107, 32727109, 32727111, 32727113, 32727115, 32727117, 32727119, 32727121, + 32727123, 32727125, 32727127, 32727129, 32727131, 32727133, 32727135, 32727137, 32727139, 32727141, 32727143, 32727145, 32727147, 32727149, 32727151, + 32727153, 32727155, 32727157, 32727159, 32727161, 32727163, 32727165, 32727167, 32751489, 32751491, 32751493, 32751495, 32751497, 32751499, 32751501, + 32751503, 32751505, 32751507, 32751509, 32751511, 32751513, 32751515, 32751517, 32751519, 32751521, 32751523, 32751525, 32751527, 32751529, 32751531, + 32751533, 32751535, 32751537, 32751539, 32751541, 32751543, 32751545, 32751547, 32751549, 32751551, 32751553, 32751555, 32751557, 32751559, 32751561, + 32751563, 32751565, 32751567, 32751569, 32751571, 32751573, 32751575, 32751577, 32751579, 32751581, 32751583, 32751585, 32751587, 32751589, 32751591, + 32751593, 32751595, 32751597, 32751599, 32751601, 32751603, 32751605, 32751607, 32751609, 32751611, 6179, 35, 0, 34, 6178, + 32743431, 32743433, 32743435, 32743437, 32743439, 32743441, 32743443, 32743445, 32743447, 32743449, 32743451, 32743453, 32743455, 32743457, 32743459, + 32743461, 32743463, 32743465, 32743467, 32743469, 32743471, 32743473, 32743475, 32743477, 32743479, 32743481, 32743483, 32743485, 32743487, 32743489, + 32743491, 32743493, 32743495, 32743497, 32743499, 32743501, 32743503, 32743505, 32743507, 32743509, 32743511, 32743513, 32743515, 32743517, 32743519, + 32743521, 32743523, 32743525, 32743527, 32743529, 32743531, 32743533, 32743535, 32743537, 32743539, 32743541, 32743543, 32743545, 32743547, 32743549, + 32743551, 32767873, 32767875, 32767877, 32767879, 32767881, 32767883, 32767885, 32767887, 32767889, 32767891, 32767893, 32767895, 32767897, 32767899, + 32767901, 32767903, 32767905, 32767907, 32767909, 32767911, 32767913, 32767915, 32767917, 32767919, 32767921, 32767923, 32767925, 32767927, 32767929, + 32767931, 32767933, 32767935, 32767937, 32767939, 32767941, 32767943, 32767945, 32767947, 32767949, 32767951, 32767953, 32767955, 32767957, 32767959, + 32767961, 32767963, 32767965, 32767967, 32767969, 32767971, 32767973, 32767975, 32767977, 32767979, 32767981, 32767983, 32767985, 32767987, 32767989, + 32767991, 32767993, 32767995, 24653, 77, 0, 76, 24652, 32759815, 32759817, 32759819, 32759821, 32759823, 32759825, 32759827, + 32759829, 32759831, 32759833, 32759835, 32759837, 32759839, 32759841, 32759843, 32759845, 32759847, 32759849, 32759851, 32759853, 32759855, 32759857, + 32759859, 32759861, 32759863, 32759865, 32759867, 32759869, 32759871, 32759873, 32759875, 32759877, 32759879, 32759881, 32759883, 32759885, 32759887, + 32759889, 32759891, 32759893, 32759895, 32759897, 32759899, 32759901, 32759903, 32759905, 32759907, 32759909, 32759911, 32759913, 32759915, 32759917, + 32759919, 32759921, 32759923, 32759925, 32759927, 32759929, 32759931, 32759933, 32759935, 32784257, 32784259, 32784261, 32784263, 32784265, 32784267, + 32784269, 32784271, 32784273, 32784275, 32784277, 32784279, 32784281, 32784283, 32784285, 32784287, 32784289, 32784291, 32784293, 32784295, 32784297, + 32784299, 32784301, 32784303, 32784305, 32784307, 32784309, 32784311, 32784313, 32784315, 32784317, 32784319, 32784321, 32784323, 32784325, 32784327, + 32784329, 32784331, 32784333, 32784335, 32784337, 32784339, 32784341, 32784343, 32784345, 32784347, 32784349, 32784351, 32784353, 32784355, 32784357, + 32784359, 32784361, 32784363, 32784365, 32784367, 32784369, 32784371, 32784373, 32784375, 32784377, 32784379, 24655, 79, 0, 78, + 24654, 32776199, 32776201, 32776203, 32776205, 32776207, 32776209, 32776211, 32776213, 32776215, 32776217, 32776219, 32776221, 32776223, 32776225, + 32776227, 32776229, 32776231, 32776233, 32776235, 32776237, 32776239, 32776241, 32776243, 32776245, 32776247, 32776249, 32776251, 32776253, 32776255, + 32776257, 32776259, 32776261, 32776263, 32776265, 32776267, 32776269, 32776271, 32776273, 32776275, 32776277, 32776279, 32776281, 32776283, 32776285, + 32776287, 32776289, 32776291, 32776293, 32776295, 32776297, 32776299, 32776301, 32776303, 32776305, 32776307, 32776309, 32776311, 32776313, 32776315, + 32776317, 32776319, 32800641, 32800643, 32800645, 32800647, 32800649, 32800651, 32800653, 32800655, 32800657, 32800659, 32800661, 32800663, 32800665, + 32800667, 32800669, 32800671, 32800673, 32800675, 32800677, 32800679, 32800681, 32800683, 32800685, 32800687, 32800689, 32800691, 32800693, 32800695, + 32800697, 32800699, 32800701, 32800703, 32800705, 32800707, 32800709, 32800711, 32800713, 32800715, 32800717, 32800719, 32800721, 32800723, 32800725, + 32800727, 32800729, 32800731, 32800733, 32800735, 32800737, 32800739, 32800741, 32800743, 32800745, 32800747, 32800749, 32800751, 32800753, 32800755, + 32800757, 32800759, 32800761, 32800763, 49337, 185, 0, 184, 49336, 32792583, 32792585, 32792587, 32792589, 32792591, 32792593, + 32792595, 32792597, 32792599, 32792601, 32792603, 32792605, 32792607, 32792609, 32792611, 32792613, 32792615, 32792617, 32792619, 32792621, 32792623, + 32792625, 32792627, 32792629, 32792631, 32792633, 32792635, 32792637, 32792639, 32792641, 32792643, 32792645, 32792647, 32792649, 32792651, 32792653, + 32792655, 32792657, 32792659, 32792661, 32792663, 32792665, 32792667, 32792669, 32792671, 32792673, 32792675, 32792677, 32792679, 32792681, 32792683, + 32792685, 32792687, 32792689, 32792691, 32792693, 32792695, 32792697, 32792699, 32792701, 32792703, 32817025, 32817027, 32817029, 32817031, 32817033, + 32817035, 32817037, 32817039, 32817041, 32817043, 32817045, 32817047, 32817049, 32817051, 32817053, 32817055, 32817057, 32817059, 32817061, 32817063, + 32817065, 32817067, 32817069, 32817071, 32817073, 32817075, 32817077, 32817079, 32817081, 32817083, 32817085, 32817087, 32817089, 32817091, 32817093, + 32817095, 32817097, 32817099, 32817101, 32817103, 32817105, 32817107, 32817109, 32817111, 32817113, 32817115, 32817117, 32817119, 32817121, 32817123, + 32817125, 32817127, 32817129, 32817131, 32817133, 32817135, 32817137, 32817139, 32817141, 32817143, 32817145, 32817147, 49339, 187, 0, + 186, 49338, 32808967, 32808969, 32808971, 32808973, 32808975, 32808977, 32808979, 32808981, 32808983, 32808985, 32808987, 32808989, 32808991, + 32808993, 32808995, 32808997, 32808999, 32809001, 32809003, 32809005, 32809007, 32809009, 32809011, 32809013, 32809015, 32809017, 32809019, 32809021, + 32809023, 32809025, 32809027, 32809029, 32809031, 32809033, 32809035, 32809037, 32809039, 32809041, 32809043, 32809045, 32809047, 32809049, 32809051, + 32809053, 32809055, 32809057, 32809059, 32809061, 32809063, 32809065, 32809067, 32809069, 32809071, 32809073, 32809075, 32809077, 32809079, 32809081, + 32809083, 32809085, 32809087, 32833409, 32833411, 32833413, 32833415, 32833417, 32833419, 32833421, 32833423, 32833425, 32833427, 32833429, 32833431, + 32833433, 32833435, 32833437, 32833439, 32833441, 32833443, 32833445, 32833447, 32833449, 32833451, 32833453, 32833455, 32833457, 32833459, 32833461, + 32833463, 32833465, 32833467, 32833469, 32833471, 32833473, 32833475, 32833477, 32833479, 32833481, 32833483, 32833485, 32833487, 32833489, 32833491, + 32833493, 32833495, 32833497, 32833499, 32833501, 32833503, 32833505, 32833507, 32833509, 32833511, 32833513, 32833515, 32833517, 32833519, 32833521, + 32833523, 32833525, 32833527, 32833529, 32833531, 49341, 189, 0, 188, 49340, 32825351, 32825353, 32825355, 32825357, 32825359, + 32825361, 32825363, 32825365, 32825367, 32825369, 32825371, 32825373, 32825375, 32825377, 32825379, 32825381, 32825383, 32825385, 32825387, 32825389, + 32825391, 32825393, 32825395, 32825397, 32825399, 32825401, 32825403, 32825405, 32825407, 32825409, 32825411, 32825413, 32825415, 32825417, 32825419, + 32825421, 32825423, 32825425, 32825427, 32825429, 32825431, 32825433, 32825435, 32825437, 32825439, 32825441, 32825443, 32825445, 32825447, 32825449, + 32825451, 32825453, 32825455, 32825457, 32825459, 32825461, 32825463, 32825465, 32825467, 32825469, 32825471, 32849793, 32849795, 32849797, 32849799, + 32849801, 32849803, 32849805, 32849807, 32849809, 32849811, 32849813, 32849815, 32849817, 32849819, 32849821, 32849823, 32849825, 32849827, 32849829, + 32849831, 32849833, 32849835, 32849837, 32849839, 32849841, 32849843, 32849845, 32849847, 32849849, 32849851, 32849853, 32849855, 32849857, 32849859, + 32849861, 32849863, 32849865, 32849867, 32849869, 32849871, 32849873, 32849875, 32849877, 32849879, 32849881, 32849883, 32849885, 32849887, 32849889, + 32849891, 32849893, 32849895, 32849897, 32849899, 32849901, 32849903, 32849905, 32849907, 32849909, 32849911, 32849913, 32849915, 49343, 191, + 0, 190, 49342, 32841735, 32841737, 32841739, 32841741, 32841743, 32841745, 32841747, 32841749, 32841751, 32841753, 32841755, 32841757, + 32841759, 32841761, 32841763, 32841765, 32841767, 32841769, 32841771, 32841773, 32841775, 32841777, 32841779, 32841781, 32841783, 32841785, 32841787, + 32841789, 32841791, 32841793, 32841795, 32841797, 32841799, 32841801, 32841803, 32841805, 32841807, 32841809, 32841811, 32841813, 32841815, 32841817, + 32841819, 32841821, 32841823, 32841825, 32841827, 32841829, 32841831, 32841833, 32841835, 32841837, 32841839, 32841841, 32841843, 32841845, 32841847, + 32841849, 32841851, 32841853, 32841855, 32866177, 32866179, 32866181, 32866183, 32866185, 32866187, 32866189, 32866191, 32866193, 32866195, 32866197, + 32866199, 32866201, 32866203, 32866205, 32866207, 32866209, 32866211, 32866213, 32866215, 32866217, 32866219, 32866221, 32866223, 32866225, 32866227, + 32866229, 32866231, 32866233, 32866235, 32866237, 32866239, 32866241, 32866243, 32866245, 32866247, 32866249, 32866251, 32866253, 32866255, 32866257, + 32866259, 32866261, 32866263, 32866265, 32866267, 32866269, 32866271, 32866273, 32866275, 32866277, 32866279, 32866281, 32866283, 32866285, 32866287, + 32866289, 32866291, 32866293, 32866295, 32866297, 32866299, 32866301, 463, 0, 462, 32858117, 32858119, 32858121, 32858123, 32858125, + 32858127, 32858129, 32858131, 32858133, 32858135, 32858137, 32858139, 32858141, 32858143, 32858145, 32858147, 32858149, 32858151, 32858153, 32858155, + 32858157, 32858159, 32858161, 32858163, 32858165, 32858167, 32858169, 32858171, 32858173, 32858175, 32858177, 32858179, 32858181, 32858183, 32858185, + 32858187, 32858189, 32858191, 32858193, 32858195, 32858197, 32858199, 32858201, 32858203, 32858205, 32858207, 32858209, 32858211, 32858213, 32858215, + 32858217, 32858219, 32858221, 32858223, 32858225, 32858227, 32858229, 32858231, 32858233, 32858235, 32858237, 32858239, 32882561, 32882563, 32882565, + 32882567, 32882569, 32882571, 32882573, 32882575, 32882577, 32882579, 32882581, 32882583, 32882585, 32882587, 32882589, 32882591, 32882593, 32882595, + 32882597, 32882599, 32882601, 32882603, 32882605, 32882607, 32882609, 32882611, 32882613, 32882615, 32882617, 32882619, 32882621, 32882623, 32882625, + 32882627, 32882629, 32882631, 32882633, 32882635, 32882637, 32882639, 32882641, 32882643, 32882645, 32882647, 32882649, 32882651, 32882653, 32882655, + 32882657, 32882659, 32882661, 32882663, 32882665, 32882667, 32882669, 32882671, 32882673, 32882675, 32882677, 32882679, 32882681, 32882683, 32882685, + 1823, 0, 1822, 32874501, 32874503, 32874505, 32874507, 32874509, 32874511, 32874513, 32874515, 32874517, 32874519, 32874521, 32874523, + 32874525, 32874527, 32874529, 32874531, 32874533, 32874535, 32874537, 32874539, 32874541, 32874543, 32874545, 32874547, 32874549, 32874551, 32874553, + 32874555, 32874557, 32874559, 32874561, 32874563, 32874565, 32874567, 32874569, 32874571, 32874573, 32874575, 32874577, 32874579, 32874581, 32874583, + 32874585, 32874587, 32874589, 32874591, 32874593, 32874595, 32874597, 32874599, 32874601, 32874603, 32874605, 32874607, 32874609, 32874611, 32874613, + 32874615, 32874617, 32874619, 32874621, 32874623, 32898945, 32898947, 32898949, 32898951, 32898953, 32898955, 32898957, 32898959, 32898961, 32898963, + 32898965, 32898967, 32898969, 32898971, 32898973, 32898975, 32898977, 32898979, 32898981, 32898983, 32898985, 32898987, 32898989, 32898991, 32898993, + 32898995, 32898997, 32898999, 32899001, 32899003, 32899005, 32899007, 32899009, 32899011, 32899013, 32899015, 32899017, 32899019, 32899021, 32899023, + 32899025, 32899027, 32899029, 32899031, 32899033, 32899035, 32899037, 32899039, 32899041, 32899043, 32899045, 32899047, 32899049, 32899051, 32899053, + 32899055, 32899057, 32899059, 32899061, 32899063, 32899065, 32899067, 32899069, 1821, 0, 1820, 32890885, 32890887, 32890889, 32890891, + 32890893, 32890895, 32890897, 32890899, 32890901, 32890903, 32890905, 32890907, 32890909, 32890911, 32890913, 32890915, 32890917, 32890919, 32890921, + 32890923, 32890925, 32890927, 32890929, 32890931, 32890933, 32890935, 32890937, 32890939, 32890941, 32890943, 32890945, 32890947, 32890949, 32890951, + 32890953, 32890955, 32890957, 32890959, 32890961, 32890963, 32890965, 32890967, 32890969, 32890971, 32890973, 32890975, 32890977, 32890979, 32890981, + 32890983, 32890985, 32890987, 32890989, 32890991, 32890993, 32890995, 32890997, 32890999, 32891001, 32891003, 32891005, 32891007, 32915329, 32915331, + 32915333, 32915335, 32915337, 32915339, 32915341, 32915343, 32915345, 32915347, 32915349, 32915351, 32915353, 32915355, 32915357, 32915359, 32915361, + 32915363, 32915365, 32915367, 32915369, 32915371, 32915373, 32915375, 32915377, 32915379, 32915381, 32915383, 32915385, 32915387, 32915389, 32915391, + 32915393, 32915395, 32915397, 32915399, 32915401, 32915403, 32915405, 32915407, 32915409, 32915411, 32915413, 32915415, 32915417, 32915419, 32915421, + 32915423, 32915425, 32915427, 32915429, 32915431, 32915433, 32915435, 32915437, 32915439, 32915441, 32915443, 32915445, 32915447, 32915449, 32915451, + 32915453, 3619, 0, 3618, 32907269, 32907271, 32907273, 32907275, 32907277, 32907279, 32907281, 32907283, 32907285, 32907287, 32907289, + 32907291, 32907293, 32907295, 32907297, 32907299, 32907301, 32907303, 32907305, 32907307, 32907309, 32907311, 32907313, 32907315, 32907317, 32907319, + 32907321, 32907323, 32907325, 32907327, 32907329, 32907331, 32907333, 32907335, 32907337, 32907339, 32907341, 32907343, 32907345, 32907347, 32907349, + 32907351, 32907353, 32907355, 32907357, 32907359, 32907361, 32907363, 32907365, 32907367, 32907369, 32907371, 32907373, 32907375, 32907377, 32907379, + 32907381, 32907383, 32907385, 32907387, 32907389, 32907391, 32931713, 32931715, 32931717, 32931719, 32931721, 32931723, 32931725, 32931727, 32931729, + 32931731, 32931733, 32931735, 32931737, 32931739, 32931741, 32931743, 32931745, 32931747, 32931749, 32931751, 32931753, 32931755, 32931757, 32931759, + 32931761, 32931763, 32931765, 32931767, 32931769, 32931771, 32931773, 32931775, 32931777, 32931779, 32931781, 32931783, 32931785, 32931787, 32931789, + 32931791, 32931793, 32931795, 32931797, 32931799, 32931801, 32931803, 32931805, 32931807, 32931809, 32931811, 32931813, 32931815, 32931817, 32931819, + 32931821, 32931823, 32931825, 32931827, 32931829, 32931831, 32931833, 32931835, 32931837, 3617, 0, 3616, 32923653, 32923655, 32923657, + 32923659, 32923661, 32923663, 32923665, 32923667, 32923669, 32923671, 32923673, 32923675, 32923677, 32923679, 32923681, 32923683, 32923685, 32923687, + 32923689, 32923691, 32923693, 32923695, 32923697, 32923699, 32923701, 32923703, 32923705, 32923707, 32923709, 32923711, 32923713, 32923715, 32923717, + 32923719, 32923721, 32923723, 32923725, 32923727, 32923729, 32923731, 32923733, 32923735, 32923737, 32923739, 32923741, 32923743, 32923745, 32923747, + 32923749, 32923751, 32923753, 32923755, 32923757, 32923759, 32923761, 32923763, 32923765, 32923767, 32923769, 32923771, 32923773, 32923775, 32948097, + 32948099, 32948101, 32948103, 32948105, 32948107, 32948109, 32948111, 32948113, 32948115, 32948117, 32948119, 32948121, 32948123, 32948125, 32948127, + 32948129, 32948131, 32948133, 32948135, 32948137, 32948139, 32948141, 32948143, 32948145, 32948147, 32948149, 32948151, 32948153, 32948155, 32948157, + 32948159, 32948161, 32948163, 32948165, 32948167, 32948169, 32948171, 32948173, 32948175, 32948177, 32948179, 32948181, 32948183, 32948185, 32948187, + 32948189, 32948191, 32948193, 32948195, 32948197, 32948199, 32948201, 32948203, 32948205, 32948207, 32948209, 32948211, 32948213, 32948215, 32948217, + 32948219, 32948221, 3623, 0, 3622, 32940037, 32940039, 32940041, 32940043, 32940045, 32940047, 32940049, 32940051, 32940053, 32940055, + 32940057, 32940059, 32940061, 32940063, 32940065, 32940067, 32940069, 32940071, 32940073, 32940075, 32940077, 32940079, 32940081, 32940083, 32940085, + 32940087, 32940089, 32940091, 32940093, 32940095, 32940097, 32940099, 32940101, 32940103, 32940105, 32940107, 32940109, 32940111, 32940113, 32940115, + 32940117, 32940119, 32940121, 32940123, 32940125, 32940127, 32940129, 32940131, 32940133, 32940135, 32940137, 32940139, 32940141, 32940143, 32940145, + 32940147, 32940149, 32940151, 32940153, 32940155, 32940157, 32940159, 32964481, 32964483, 32964485, 32964487, 32964489, 32964491, 32964493, 32964495, + 32964497, 32964499, 32964501, 32964503, 32964505, 32964507, 32964509, 32964511, 32964513, 32964515, 32964517, 32964519, 32964521, 32964523, 32964525, + 32964527, 32964529, 32964531, 32964533, 32964535, 32964537, 32964539, 32964541, 32964543, 32964545, 32964547, 32964549, 32964551, 32964553, 32964555, + 32964557, 32964559, 32964561, 32964563, 32964565, 32964567, 32964569, 32964571, 32964573, 32964575, 32964577, 32964579, 32964581, 32964583, 32964585, + 32964587, 32964589, 32964591, 32964593, 32964595, 32964597, 32964599, 32964601, 32964603, 32964605, 7211, 0, 7210, 32956421, 32956423, + 32956425, 32956427, 32956429, 32956431, 32956433, 32956435, 32956437, 32956439, 32956441, 32956443, 32956445, 32956447, 32956449, 32956451, 32956453, + 32956455, 32956457, 32956459, 32956461, 32956463, 32956465, 32956467, 32956469, 32956471, 32956473, 32956475, 32956477, 32956479, 32956481, 32956483, + 32956485, 32956487, 32956489, 32956491, 32956493, 32956495, 32956497, 32956499, 32956501, 32956503, 32956505, 32956507, 32956509, 32956511, 32956513, + 32956515, 32956517, 32956519, 32956521, 32956523, 32956525, 32956527, 32956529, 32956531, 32956533, 32956535, 32956537, 32956539, 32956541, 32956543, + 32980865, 32980867, 32980869, 32980871, 32980873, 32980875, 32980877, 32980879, 32980881, 32980883, 32980885, 32980887, 32980889, 32980891, 32980893, + 32980895, 32980897, 32980899, 32980901, 32980903, 32980905, 32980907, 32980909, 32980911, 32980913, 32980915, 32980917, 32980919, 32980921, 32980923, + 32980925, 32980927, 32980929, 32980931, 32980933, 32980935, 32980937, 32980939, 32980941, 32980943, 32980945, 32980947, 32980949, 32980951, 32980953, + 32980955, 32980957, 32980959, 32980961, 32980963, 32980965, 32980967, 32980969, 32980971, 32980973, 32980975, 32980977, 32980979, 32980981, 32980983, + 32980985, 32980987, 32980989, 7209, 0, 7208, 32972805, 32972807, 32972809, 32972811, 32972813, 32972815, 32972817, 32972819, 32972821, + 32972823, 32972825, 32972827, 32972829, 32972831, 32972833, 32972835, 32972837, 32972839, 32972841, 32972843, 32972845, 32972847, 32972849, 32972851, + 32972853, 32972855, 32972857, 32972859, 32972861, 32972863, 32972865, 32972867, 32972869, 32972871, 32972873, 32972875, 32972877, 32972879, 32972881, + 32972883, 32972885, 32972887, 32972889, 32972891, 32972893, 32972895, 32972897, 32972899, 32972901, 32972903, 32972905, 32972907, 32972909, 32972911, + 32972913, 32972915, 32972917, 32972919, 32972921, 32972923, 32972925, 32972927, 32997249, 32997251, 32997253, 32997255, 32997257, 32997259, 32997261, + 32997263, 32997265, 32997267, 32997269, 32997271, 32997273, 32997275, 32997277, 32997279, 32997281, 32997283, 32997285, 32997287, 32997289, 32997291, + 32997293, 32997295, 32997297, 32997299, 32997301, 32997303, 32997305, 32997307, 32997309, 32997311, 32997313, 32997315, 32997317, 32997319, 32997321, + 32997323, 32997325, 32997327, 32997329, 32997331, 32997333, 32997335, 32997337, 32997339, 32997341, 32997343, 32997345, 32997347, 32997349, 32997351, + 32997353, 32997355, 32997357, 32997359, 32997361, 32997363, 32997365, 32997367, 32997369, 32997371, 32997373, 7207, 0, 7206, 32989189, + 32989191, 32989193, 32989195, 32989197, 32989199, 32989201, 32989203, 32989205, 32989207, 32989209, 32989211, 32989213, 32989215, 32989217, 32989219, + 32989221, 32989223, 32989225, 32989227, 32989229, 32989231, 32989233, 32989235, 32989237, 32989239, 32989241, 32989243, 32989245, 32989247, 32989249, + 32989251, 32989253, 32989255, 32989257, 32989259, 32989261, 32989263, 32989265, 32989267, 32989269, 32989271, 32989273, 32989275, 32989277, 32989279, + 32989281, 32989283, 32989285, 32989287, 32989289, 32989291, 32989293, 32989295, 32989297, 32989299, 32989301, 32989303, 32989305, 32989307, 32989309, + 32989311, 33013633, 33013635, 33013637, 33013639, 33013641, 33013643, 33013645, 33013647, 33013649, 33013651, 33013653, 33013655, 33013657, 33013659, + 33013661, 33013663, 33013665, 33013667, 33013669, 33013671, 33013673, 33013675, 33013677, 33013679, 33013681, 33013683, 33013685, 33013687, 33013689, + 33013691, 33013693, 33013695, 33013697, 33013699, 33013701, 33013703, 33013705, 33013707, 33013709, 33013711, 33013713, 33013715, 33013717, 33013719, + 33013721, 33013723, 33013725, 33013727, 33013729, 33013731, 33013733, 33013735, 33013737, 33013739, 33013741, 33013743, 33013745, 33013747, 33013749, + 33013751, 33013753, 33013755, 33013757, 7221, 0, 7220, 33005573, 33005575, 33005577, 33005579, 33005581, 33005583, 33005585, 33005587, + 33005589, 33005591, 33005593, 33005595, 33005597, 33005599, 33005601, 33005603, 33005605, 33005607, 33005609, 33005611, 33005613, 33005615, 33005617, + 33005619, 33005621, 33005623, 33005625, 33005627, 33005629, 33005631, 33005633, 33005635, 33005637, 33005639, 33005641, 33005643, 33005645, 33005647, + 33005649, 33005651, 33005653, 33005655, 33005657, 33005659, 33005661, 33005663, 33005665, 33005667, 33005669, 33005671, 33005673, 33005675, 33005677, + 33005679, 33005681, 33005683, 33005685, 33005687, 33005689, 33005691, 33005693, 33005695, 33030017, 33030019, 33030021, 33030023, 33030025, 33030027, + 33030029, 33030031, 33030033, 33030035, 33030037, 33030039, 33030041, 33030043, 33030045, 33030047, 33030049, 33030051, 33030053, 33030055, 33030057, + 33030059, 33030061, 33030063, 33030065, 33030067, 33030069, 33030071, 33030073, 33030075, 33030077, 33030079, 33030081, 33030083, 33030085, 33030087, + 33030089, 33030091, 33030093, 33030095, 33030097, 33030099, 33030101, 33030103, 33030105, 33030107, 33030109, 33030111, 33030113, 33030115, 33030117, + 33030119, 33030121, 33030123, 33030125, 33030127, 33030129, 33030131, 33030133, 33030135, 33030137, 33030139, 33030141, 14379, 0, 14378, + 33021957, 33021959, 33021961, 33021963, 33021965, 33021967, 33021969, 33021971, 33021973, 33021975, 33021977, 33021979, 33021981, 33021983, 33021985, + 33021987, 33021989, 33021991, 33021993, 33021995, 33021997, 33021999, 33022001, 33022003, 33022005, 33022007, 33022009, 33022011, 33022013, 33022015, + 33022017, 33022019, 33022021, 33022023, 33022025, 33022027, 33022029, 33022031, 33022033, 33022035, 33022037, 33022039, 33022041, 33022043, 33022045, + 33022047, 33022049, 33022051, 33022053, 33022055, 33022057, 33022059, 33022061, 33022063, 33022065, 33022067, 33022069, 33022071, 33022073, 33022075, + 33022077, 33022079, 33046401, 33046403, 33046405, 33046407, 33046409, 33046411, 33046413, 33046415, 33046417, 33046419, 33046421, 33046423, 33046425, + 33046427, 33046429, 33046431, 33046433, 33046435, 33046437, 33046439, 33046441, 33046443, 33046445, 33046447, 33046449, 33046451, 33046453, 33046455, + 33046457, 33046459, 33046461, 33046463, 33046465, 33046467, 33046469, 33046471, 33046473, 33046475, 33046477, 33046479, 33046481, 33046483, 33046485, + 33046487, 33046489, 33046491, 33046493, 33046495, 33046497, 33046499, 33046501, 33046503, 33046505, 33046507, 33046509, 33046511, 33046513, 33046515, + 33046517, 33046519, 33046521, 33046523, 33046525, 14377, 0, 14376, 33038341, 33038343, 33038345, 33038347, 33038349, 33038351, 33038353, + 33038355, 33038357, 33038359, 33038361, 33038363, 33038365, 33038367, 33038369, 33038371, 33038373, 33038375, 33038377, 33038379, 33038381, 33038383, + 33038385, 33038387, 33038389, 33038391, 33038393, 33038395, 33038397, 33038399, 33038401, 33038403, 33038405, 33038407, 33038409, 33038411, 33038413, + 33038415, 33038417, 33038419, 33038421, 33038423, 33038425, 33038427, 33038429, 33038431, 33038433, 33038435, 33038437, 33038439, 33038441, 33038443, + 33038445, 33038447, 33038449, 33038451, 33038453, 33038455, 33038457, 33038459, 33038461, 33038463, 33062785, 33062787, 33062789, 33062791, 33062793, + 33062795, 33062797, 33062799, 33062801, 33062803, 33062805, 33062807, 33062809, 33062811, 33062813, 33062815, 33062817, 33062819, 33062821, 33062823, + 33062825, 33062827, 33062829, 33062831, 33062833, 33062835, 33062837, 33062839, 33062841, 33062843, 33062845, 33062847, 33062849, 33062851, 33062853, + 33062855, 33062857, 33062859, 33062861, 33062863, 33062865, 33062867, 33062869, 33062871, 33062873, 33062875, 33062877, 33062879, 33062881, 33062883, + 33062885, 33062887, 33062889, 33062891, 33062893, 33062895, 33062897, 33062899, 33062901, 33062903, 33062905, 33062907, 33062909, 14375, 0, + 14374, 33054725, 33054727, 33054729, 33054731, 33054733, 33054735, 33054737, 33054739, 33054741, 33054743, 33054745, 33054747, 33054749, 33054751, + 33054753, 33054755, 33054757, 33054759, 33054761, 33054763, 33054765, 33054767, 33054769, 33054771, 33054773, 33054775, 33054777, 33054779, 33054781, + 33054783, 33054785, 33054787, 33054789, 33054791, 33054793, 33054795, 33054797, 33054799, 33054801, 33054803, 33054805, 33054807, 33054809, 33054811, + 33054813, 33054815, 33054817, 33054819, 33054821, 33054823, 33054825, 33054827, 33054829, 33054831, 33054833, 33054835, 33054837, 33054839, 33054841, + 33054843, 33054845, 33054847, 33079169, 33079171, 33079173, 33079175, 33079177, 33079179, 33079181, 33079183, 33079185, 33079187, 33079189, 33079191, + 33079193, 33079195, 33079197, 33079199, 33079201, 33079203, 33079205, 33079207, 33079209, 33079211, 33079213, 33079215, 33079217, 33079219, 33079221, + 33079223, 33079225, 33079227, 33079229, 33079231, 33079233, 33079235, 33079237, 33079239, 33079241, 33079243, 33079245, 33079247, 33079249, 33079251, + 33079253, 33079255, 33079257, 33079259, 33079261, 33079263, 33079265, 33079267, 33079269, 33079271, 33079273, 33079275, 33079277, 33079279, 33079281, + 33079283, 33079285, 33079287, 33079289, 33079291, 33079293, 14373, 0, 14372, 33071109, 33071111, 33071113, 33071115, 33071117, 33071119, + 33071121, 33071123, 33071125, 33071127, 33071129, 33071131, 33071133, 33071135, 33071137, 33071139, 33071141, 33071143, 33071145, 33071147, 33071149, + 33071151, 33071153, 33071155, 33071157, 33071159, 33071161, 33071163, 33071165, 33071167, 33071169, 33071171, 33071173, 33071175, 33071177, 33071179, + 33071181, 33071183, 33071185, 33071187, 33071189, 33071191, 33071193, 33071195, 33071197, 33071199, 33071201, 33071203, 33071205, 33071207, 33071209, + 33071211, 33071213, 33071215, 33071217, 33071219, 33071221, 33071223, 33071225, 33071227, 33071229, 33071231, 33095553, 33095555, 33095557, 33095559, + 33095561, 33095563, 33095565, 33095567, 33095569, 33095571, 33095573, 33095575, 33095577, 33095579, 33095581, 33095583, 33095585, 33095587, 33095589, + 33095591, 33095593, 33095595, 33095597, 33095599, 33095601, 33095603, 33095605, 33095607, 33095609, 33095611, 33095613, 33095615, 33095617, 33095619, + 33095621, 33095623, 33095625, 33095627, 33095629, 33095631, 33095633, 33095635, 33095637, 33095639, 33095641, 33095643, 33095645, 33095647, 33095649, + 33095651, 33095653, 33095655, 33095657, 33095659, 33095661, 33095663, 33095665, 33095667, 33095669, 33095671, 33095673, 33095675, 33095677, 14371, + 0, 14370, 33087493, 33087495, 33087497, 33087499, 33087501, 33087503, 33087505, 33087507, 33087509, 33087511, 33087513, 33087515, 33087517, + 33087519, 33087521, 33087523, 33087525, 33087527, 33087529, 33087531, 33087533, 33087535, 33087537, 33087539, 33087541, 33087543, 33087545, 33087547, + 33087549, 33087551, 33087553, 33087555, 33087557, 33087559, 33087561, 33087563, 33087565, 33087567, 33087569, 33087571, 33087573, 33087575, 33087577, + 33087579, 33087581, 33087583, 33087585, 33087587, 33087589, 33087591, 33087593, 33087595, 33087597, 33087599, 33087601, 33087603, 33087605, 33087607, + 33087609, 33087611, 33087613, 33087615, 33111937, 33111939, 33111941, 33111943, 33111945, 33111947, 33111949, 33111951, 33111953, 33111955, 33111957, + 33111959, 33111961, 33111963, 33111965, 33111967, 33111969, 33111971, 33111973, 33111975, 33111977, 33111979, 33111981, 33111983, 33111985, 33111987, + 33111989, 33111991, 33111993, 33111995, 33111997, 33111999, 33112001, 33112003, 33112005, 33112007, 33112009, 33112011, 33112013, 33112015, 33112017, + 33112019, 33112021, 33112023, 33112025, 33112027, 33112029, 33112031, 33112033, 33112035, 33112037, 33112039, 33112041, 33112043, 33112045, 33112047, + 33112049, 33112051, 33112053, 33112055, 33112057, 33112059, 33112061, 57421, 0, 57420, 33103877, 33103879, 33103881, 33103883, 33103885, + 33103887, 33103889, 33103891, 33103893, 33103895, 33103897, 33103899, 33103901, 33103903, 33103905, 33103907, 33103909, 33103911, 33103913, 33103915, + 33103917, 33103919, 33103921, 33103923, 33103925, 33103927, 33103929, 33103931, 33103933, 33103935, 33103937, 33103939, 33103941, 33103943, 33103945, + 33103947, 33103949, 33103951, 33103953, 33103955, 33103957, 33103959, 33103961, 33103963, 33103965, 33103967, 33103969, 33103971, 33103973, 33103975, + 33103977, 33103979, 33103981, 33103983, 33103985, 33103987, 33103989, 33103991, 33103993, 33103995, 33103997, 33103999, 33128321, 33128323, 33128325, + 33128327, 33128329, 33128331, 33128333, 33128335, 33128337, 33128339, 33128341, 33128343, 33128345, 33128347, 33128349, 33128351, 33128353, 33128355, + 33128357, 33128359, 33128361, 33128363, 33128365, 33128367, 33128369, 33128371, 33128373, 33128375, 33128377, 33128379, 33128381, 33128383, 33128385, + 33128387, 33128389, 33128391, 33128393, 33128395, 33128397, 33128399, 33128401, 33128403, 33128405, 33128407, 33128409, 33128411, 33128413, 33128415, + 33128417, 33128419, 33128421, 33128423, 33128425, 33128427, 33128429, 33128431, 33128433, 33128435, 33128437, 33128439, 33128441, 33128443, 33128445, + 57423, 0, 57422, 33120261, 33120263, 33120265, 33120267, 33120269, 33120271, 33120273, 33120275, 33120277, 33120279, 33120281, 33120283, + 33120285, 33120287, 33120289, 33120291, 33120293, 33120295, 33120297, 33120299, 33120301, 33120303, 33120305, 33120307, 33120309, 33120311, 33120313, + 33120315, 33120317, 33120319, 33120321, 33120323, 33120325, 33120327, 33120329, 33120331, 33120333, 33120335, 33120337, 33120339, 33120341, 33120343, + 33120345, 33120347, 33120349, 33120351, 33120353, 33120355, 33120357, 33120359, 33120361, 33120363, 33120365, 33120367, 33120369, 33120371, 33120373, + 33120375, 33120377, 33120379, 33120381, 33120383, 33144705, 33144707, 33144709, 33144711, 33144713, 33144715, 33144717, 33144719, 33144721, 33144723, + 33144725, 33144727, 33144729, 33144731, 33144733, 33144735, 33144737, 33144739, 33144741, 33144743, 33144745, 33144747, 33144749, 33144751, 33144753, + 33144755, 33144757, 33144759, 33144761, 33144763, 33144765, 33144767, 33144769, 33144771, 33144773, 33144775, 33144777, 33144779, 33144781, 33144783, + 33144785, 33144787, 33144789, 33144791, 33144793, 33144795, 33144797, 33144799, 33144801, 33144803, 33144805, 33144807, 33144809, 33144811, 33144813, + 33144815, 33144817, 33144819, 33144821, 33144823, 33144825, 33144827, 33144829, 114873, 0, 114872, 33136645, 33136647, 33136649, 33136651, + 33136653, 33136655, 33136657, 33136659, 33136661, 33136663, 33136665, 33136667, 33136669, 33136671, 33136673, 33136675, 33136677, 33136679, 33136681, + 33136683, 33136685, 33136687, 33136689, 33136691, 33136693, 33136695, 33136697, 33136699, 33136701, 33136703, 33136705, 33136707, 33136709, 33136711, + 33136713, 33136715, 33136717, 33136719, 33136721, 33136723, 33136725, 33136727, 33136729, 33136731, 33136733, 33136735, 33136737, 33136739, 33136741, + 33136743, 33136745, 33136747, 33136749, 33136751, 33136753, 33136755, 33136757, 33136759, 33136761, 33136763, 33136765, 33136767, 33161089, 33161091, + 33161093, 33161095, 33161097, 33161099, 33161101, 33161103, 33161105, 33161107, 33161109, 33161111, 33161113, 33161115, 33161117, 33161119, 33161121, + 33161123, 33161125, 33161127, 33161129, 33161131, 33161133, 33161135, 33161137, 33161139, 33161141, 33161143, 33161145, 33161147, 33161149, 33161151, + 33161153, 33161155, 33161157, 33161159, 33161161, 33161163, 33161165, 33161167, 33161169, 33161171, 33161173, 33161175, 33161177, 33161179, 33161181, + 33161183, 33161185, 33161187, 33161189, 33161191, 33161193, 33161195, 33161197, 33161199, 33161201, 33161203, 33161205, 33161207, 33161209, 33161211, + 33161213, 114875, 0, 114874, 33153029, 33153031, 33153033, 33153035, 33153037, 33153039, 33153041, 33153043, 33153045, 33153047, 33153049, + 33153051, 33153053, 33153055, 33153057, 33153059, 33153061, 33153063, 33153065, 33153067, 33153069, 33153071, 33153073, 33153075, 33153077, 33153079, + 33153081, 33153083, 33153085, 33153087, 33153089, 33153091, 33153093, 33153095, 33153097, 33153099, 33153101, 33153103, 33153105, 33153107, 33153109, + 33153111, 33153113, 33153115, 33153117, 33153119, 33153121, 33153123, 33153125, 33153127, 33153129, 33153131, 33153133, 33153135, 33153137, 33153139, + 33153141, 33153143, 33153145, 33153147, 33153149, 33153151, 33177473, 33177475, 33177477, 33177479, 33177481, 33177483, 33177485, 33177487, 33177489, + 33177491, 33177493, 33177495, 33177497, 33177499, 33177501, 33177503, 33177505, 33177507, 33177509, 33177511, 33177513, 33177515, 33177517, 33177519, + 33177521, 33177523, 33177525, 33177527, 33177529, 33177531, 33177533, 33177535, 33177537, 33177539, 33177541, 33177543, 33177545, 33177547, 33177549, + 33177551, 33177553, 33177555, 33177557, 33177559, 33177561, 33177563, 33177565, 33177567, 33177569, 33177571, 33177573, 33177575, 33177577, 33177579, + 33177581, 33177583, 33177585, 33177587, 33177589, 33177591, 33177593, 33177595, 33177597, 114877, 0, 114876, 33169413, 33169415, 33169417, + 33169419, 33169421, 33169423, 33169425, 33169427, 33169429, 33169431, 33169433, 33169435, 33169437, 33169439, 33169441, 33169443, 33169445, 33169447, + 33169449, 33169451, 33169453, 33169455, 33169457, 33169459, 33169461, 33169463, 33169465, 33169467, 33169469, 33169471, 33169473, 33169475, 33169477, + 33169479, 33169481, 33169483, 33169485, 33169487, 33169489, 33169491, 33169493, 33169495, 33169497, 33169499, 33169501, 33169503, 33169505, 33169507, + 33169509, 33169511, 33169513, 33169515, 33169517, 33169519, 33169521, 33169523, 33169525, 33169527, 33169529, 33169531, 33169533, 33169535, 33193857, + 33193859, 33193861, 33193863, 33193865, 33193867, 33193869, 33193871, 33193873, 33193875, 33193877, 33193879, 33193881, 33193883, 33193885, 33193887, + 33193889, 33193891, 33193893, 33193895, 33193897, 33193899, 33193901, 33193903, 33193905, 33193907, 33193909, 33193911, 33193913, 33193915, 33193917, + 33193919, 33193921, 33193923, 33193925, 33193927, 33193929, 33193931, 33193933, 33193935, 33193937, 33193939, 33193941, 33193943, 33193945, 33193947, + 33193949, 33193951, 33193953, 33193955, 33193957, 33193959, 33193961, 33193963, 33193965, 33193967, 33193969, 33193971, 33193973, 33193975, 33193977, + 33193979, 33193981, 114879, 0, 114878, 33185797, 33185799, 33185801, 33185803, 33185805, 33185807, 33185809, 33185811, 33185813, 33185815, + 33185817, 33185819, 33185821, 33185823, 33185825, 33185827, 33185829, 33185831, 33185833, 33185835, 33185837, 33185839, 33185841, 33185843, 33185845, + 33185847, 33185849, 33185851, 33185853, 33185855, 33185857, 33185859, 33185861, 33185863, 33185865, 33185867, 33185869, 33185871, 33185873, 33185875, + 33185877, 33185879, 33185881, 33185883, 33185885, 33185887, 33185889, 33185891, 33185893, 33185895, 33185897, 33185899, 33185901, 33185903, 33185905, + 33185907, 33185909, 33185911, 33185913, 33185915, 33185917, 33185919, 33210241, 33210243, 33210245, 33210247, 33210249, 33210251, 33210253, 33210255, + 33210257, 33210259, 33210261, 33210263, 33210265, 33210267, 33210269, 33210271, 33210273, 33210275, 33210277, 33210279, 33210281, 33210283, 33210285, + 33210287, 33210289, 33210291, 33210293, 33210295, 33210297, 33210299, 33210301, 33210303, 33210305, 33210307, 33210309, 33210311, 33210313, 33210315, + 33210317, 33210319, 33210321, 33210323, 33210325, 33210327, 33210329, 33210331, 33210333, 33210335, 33210337, 33210339, 33210341, 33210343, 33210345, + 33210347, 33210349, 33210351, 33210353, 33210355, 33210357, 33210359, 33210361, 33210363, 33210365, 33210367, 0, 33202179, 33202181, 33202183, + 33202185, 33202187, 33202189, 33202191, 33202193, 33202195, 33202197, 33202199, 33202201, 33202203, 33202205, 33202207, 33202209, 33202211, 33202213, + 33202215, 33202217, 33202219, 33202221, 33202223, 33202225, 33202227, 33202229, 33202231, 33202233, 33202235, 33202237, 33202239, 33202241, 33202243, + 33202245, 33202247, 33202249, 33202251, 33202253, 33202255, 33202257, 33202259, 33202261, 33202263, 33202265, 33202267, 33202269, 33202271, 33202273, + 33202275, 33202277, 33202279, 33202281, 33202283, 33202285, 33202287, 33202289, 33202291, 33202293, 33202295, 33202297, 33202299, 33202301, 33202303, + 33226625, 33226627, 33226629, 33226631, 33226633, 33226635, 33226637, 33226639, 33226641, 33226643, 33226645, 33226647, 33226649, 33226651, 33226653, + 33226655, 33226657, 33226659, 33226661, 33226663, 33226665, 33226667, 33226669, 33226671, 33226673, 33226675, 33226677, 33226679, 33226681, 33226683, + 33226685, 33226687, 33226689, 33226691, 33226693, 33226695, 33226697, 33226699, 33226701, 33226703, 33226705, 33226707, 33226709, 33226711, 33226713, + 33226715, 33226717, 33226719, 33226721, 33226723, 33226725, 33226727, 33226729, 33226731, 33226733, 33226735, 33226737, 33226739, 33226741, 33226743, + 33226745, 33226747, 33226749, 33226751, 0, 33218563, 33218565, 33218567, 33218569, 33218571, 33218573, 33218575, 33218577, 33218579, 33218581, + 33218583, 33218585, 33218587, 33218589, 33218591, 33218593, 33218595, 33218597, 33218599, 33218601, 33218603, 33218605, 33218607, 33218609, 33218611, + 33218613, 33218615, 33218617, 33218619, 33218621, 33218623, 33218625, 33218627, 33218629, 33218631, 33218633, 33218635, 33218637, 33218639, 33218641, + 33218643, 33218645, 33218647, 33218649, 33218651, 33218653, 33218655, 33218657, 33218659, 33218661, 33218663, 33218665, 33218667, 33218669, 33218671, + 33218673, 33218675, 33218677, 33218679, 33218681, 33218683, 33218685, 33218687, 33243009, 33243011, 33243013, 33243015, 33243017, 33243019, 33243021, + 33243023, 33243025, 33243027, 33243029, 33243031, 33243033, 33243035, 33243037, 33243039, 33243041, 33243043, 33243045, 33243047, 33243049, 33243051, + 33243053, 33243055, 33243057, 33243059, 33243061, 33243063, 33243065, 33243067, 33243069, 33243071, 33243073, 33243075, 33243077, 33243079, 33243081, + 33243083, 33243085, 33243087, 33243089, 33243091, 33243093, 33243095, 33243097, 33243099, 33243101, 33243103, 33243105, 33243107, 33243109, 33243111, + 33243113, 33243115, 33243117, 33243119, 33243121, 33243123, 33243125, 33243127, 33243129, 33243131, 33243133, 33243135, 0, 33234947, 33234949, + 33234951, 33234953, 33234955, 33234957, 33234959, 33234961, 33234963, 33234965, 33234967, 33234969, 33234971, 33234973, 33234975, 33234977, 33234979, + 33234981, 33234983, 33234985, 33234987, 33234989, 33234991, 33234993, 33234995, 33234997, 33234999, 33235001, 33235003, 33235005, 33235007, 33235009, + 33235011, 33235013, 33235015, 33235017, 33235019, 33235021, 33235023, 33235025, 33235027, 33235029, 33235031, 33235033, 33235035, 33235037, 33235039, + 33235041, 33235043, 33235045, 33235047, 33235049, 33235051, 33235053, 33235055, 33235057, 33235059, 33235061, 33235063, 33235065, 33235067, 33235069, + 33235071, 33259393, 33259395, 33259397, 33259399, 33259401, 33259403, 33259405, 33259407, 33259409, 33259411, 33259413, 33259415, 33259417, 33259419, + 33259421, 33259423, 33259425, 33259427, 33259429, 33259431, 33259433, 33259435, 33259437, 33259439, 33259441, 33259443, 33259445, 33259447, 33259449, + 33259451, 33259453, 33259455, 33259457, 33259459, 33259461, 33259463, 33259465, 33259467, 33259469, 33259471, 33259473, 33259475, 33259477, 33259479, + 33259481, 33259483, 33259485, 33259487, 33259489, 33259491, 33259493, 33259495, 33259497, 33259499, 33259501, 33259503, 33259505, 33259507, 33259509, + 33259511, 33259513, 33259515, 33259517, 33259519, 0, 33251331, 33251333, 33251335, 33251337, 33251339, 33251341, 33251343, 33251345, 33251347, + 33251349, 33251351, 33251353, 33251355, 33251357, 33251359, 33251361, 33251363, 33251365, 33251367, 33251369, 33251371, 33251373, 33251375, 33251377, + 33251379, 33251381, 33251383, 33251385, 33251387, 33251389, 33251391, 33251393, 33251395, 33251397, 33251399, 33251401, 33251403, 33251405, 33251407, + 33251409, 33251411, 33251413, 33251415, 33251417, 33251419, 33251421, 33251423, 33251425, 33251427, 33251429, 33251431, 33251433, 33251435, 33251437, + 33251439, 33251441, 33251443, 33251445, 33251447, 33251449, 33251451, 33251453, 33251455, 33275777, 33275779, 33275781, 33275783, 33275785, 33275787, + 33275789, 33275791, 33275793, 33275795, 33275797, 33275799, 33275801, 33275803, 33275805, 33275807, 33275809, 33275811, 33275813, 33275815, 33275817, + 33275819, 33275821, 33275823, 33275825, 33275827, 33275829, 33275831, 33275833, 33275835, 33275837, 33275839, 33275841, 33275843, 33275845, 33275847, + 33275849, 33275851, 33275853, 33275855, 33275857, 33275859, 33275861, 33275863, 33275865, 33275867, 33275869, 33275871, 33275873, 33275875, 33275877, + 33275879, 33275881, 33275883, 33275885, 33275887, 33275889, 33275891, 33275893, 33275895, 33275897, 33275899, 33275901, 33275903, 0, 33267715, + 33267717, 33267719, 33267721, 33267723, 33267725, 33267727, 33267729, 33267731, 33267733, 33267735, 33267737, 33267739, 33267741, 33267743, 33267745, + 33267747, 33267749, 33267751, 33267753, 33267755, 33267757, 33267759, 33267761, 33267763, 33267765, 33267767, 33267769, 33267771, 33267773, 33267775, + 33267777, 33267779, 33267781, 33267783, 33267785, 33267787, 33267789, 33267791, 33267793, 33267795, 33267797, 33267799, 33267801, 33267803, 33267805, + 33267807, 33267809, 33267811, 33267813, 33267815, 33267817, 33267819, 33267821, 33267823, 33267825, 33267827, 33267829, 33267831, 33267833, 33267835, + 33267837, 33267839, 33292161, 33292163, 33292165, 33292167, 33292169, 33292171, 33292173, 33292175, 33292177, 33292179, 33292181, 33292183, 33292185, + 33292187, 33292189, 33292191, 33292193, 33292195, 33292197, 33292199, 33292201, 33292203, 33292205, 33292207, 33292209, 33292211, 33292213, 33292215, + 33292217, 33292219, 33292221, 33292223, 33292225, 33292227, 33292229, 33292231, 33292233, 33292235, 33292237, 33292239, 33292241, 33292243, 33292245, + 33292247, 33292249, 33292251, 33292253, 33292255, 33292257, 33292259, 33292261, 33292263, 33292265, 33292267, 33292269, 33292271, 33292273, 33292275, + 33292277, 33292279, 33292281, 33292283, 33292285, 33292287, 0, 33284099, 33284101, 33284103, 33284105, 33284107, 33284109, 33284111, 33284113, + 33284115, 33284117, 33284119, 33284121, 33284123, 33284125, 33284127, 33284129, 33284131, 33284133, 33284135, 33284137, 33284139, 33284141, 33284143, + 33284145, 33284147, 33284149, 33284151, 33284153, 33284155, 33284157, 33284159, 33284161, 33284163, 33284165, 33284167, 33284169, 33284171, 33284173, + 33284175, 33284177, 33284179, 33284181, 33284183, 33284185, 33284187, 33284189, 33284191, 33284193, 33284195, 33284197, 33284199, 33284201, 33284203, + 33284205, 33284207, 33284209, 33284211, 33284213, 33284215, 33284217, 33284219, 33284221, 33284223, 33308545, 33308547, 33308549, 33308551, 33308553, + 33308555, 33308557, 33308559, 33308561, 33308563, 33308565, 33308567, 33308569, 33308571, 33308573, 33308575, 33308577, 33308579, 33308581, 33308583, + 33308585, 33308587, 33308589, 33308591, 33308593, 33308595, 33308597, 33308599, 33308601, 33308603, 33308605, 33308607, 33308609, 33308611, 33308613, + 33308615, 33308617, 33308619, 33308621, 33308623, 33308625, 33308627, 33308629, 33308631, 33308633, 33308635, 33308637, 33308639, 33308641, 33308643, + 33308645, 33308647, 33308649, 33308651, 33308653, 33308655, 33308657, 33308659, 33308661, 33308663, 33308665, 33308667, 33308669, 33308671, 0, + 33300483, 33300485, 33300487, 33300489, 33300491, 33300493, 33300495, 33300497, 33300499, 33300501, 33300503, 33300505, 33300507, 33300509, 33300511, + 33300513, 33300515, 33300517, 33300519, 33300521, 33300523, 33300525, 33300527, 33300529, 33300531, 33300533, 33300535, 33300537, 33300539, 33300541, + 33300543, 33300545, 33300547, 33300549, 33300551, 33300553, 33300555, 33300557, 33300559, 33300561, 33300563, 33300565, 33300567, 33300569, 33300571, + 33300573, 33300575, 33300577, 33300579, 33300581, 33300583, 33300585, 33300587, 33300589, 33300591, 33300593, 33300595, 33300597, 33300599, 33300601, + 33300603, 33300605, 33300607, 33324929, 33324931, 33324933, 33324935, 33324937, 33324939, 33324941, 33324943, 33324945, 33324947, 33324949, 33324951, + 33324953, 33324955, 33324957, 33324959, 33324961, 33324963, 33324965, 33324967, 33324969, 33324971, 33324973, 33324975, 33324977, 33324979, 33324981, + 33324983, 33324985, 33324987, 33324989, 33324991, 33324993, 33324995, 33324997, 33324999, 33325001, 33325003, 33325005, 33325007, 33325009, 33325011, + 33325013, 33325015, 33325017, 33325019, 33325021, 33325023, 33325025, 33325027, 33325029, 33325031, 33325033, 33325035, 33325037, 33325039, 33325041, + 33325043, 33325045, 33325047, 33325049, 33325051, 33325053, 33325055, 0, 33316867, 33316869, 33316871, 33316873, 33316875, 33316877, 33316879, + 33316881, 33316883, 33316885, 33316887, 33316889, 33316891, 33316893, 33316895, 33316897, 33316899, 33316901, 33316903, 33316905, 33316907, 33316909, + 33316911, 33316913, 33316915, 33316917, 33316919, 33316921, 33316923, 33316925, 33316927, 33316929, 33316931, 33316933, 33316935, 33316937, 33316939, + 33316941, 33316943, 33316945, 33316947, 33316949, 33316951, 33316953, 33316955, 33316957, 33316959, 33316961, 33316963, 33316965, 33316967, 33316969, + 33316971, 33316973, 33316975, 33316977, 33316979, 33316981, 33316983, 33316985, 33316987, 33316989, 33316991, 33341313, 33341315, 33341317, 33341319, + 33341321, 33341323, 33341325, 33341327, 33341329, 33341331, 33341333, 33341335, 33341337, 33341339, 33341341, 33341343, 33341345, 33341347, 33341349, + 33341351, 33341353, 33341355, 33341357, 33341359, 33341361, 33341363, 33341365, 33341367, 33341369, 33341371, 33341373, 33341375, 33341377, 33341379, + 33341381, 33341383, 33341385, 33341387, 33341389, 33341391, 33341393, 33341395, 33341397, 33341399, 33341401, 33341403, 33341405, 33341407, 33341409, + 33341411, 33341413, 33341415, 33341417, 33341419, 33341421, 33341423, 33341425, 33341427, 33341429, 33341431, 33341433, 33341435, 33341437, 33341439, + 0, 33333251, 33333253, 33333255, 33333257, 33333259, 33333261, 33333263, 33333265, 33333267, 33333269, 33333271, 33333273, 33333275, 33333277, + 33333279, 33333281, 33333283, 33333285, 33333287, 33333289, 33333291, 33333293, 33333295, 33333297, 33333299, 33333301, 33333303, 33333305, 33333307, + 33333309, 33333311, 33333313, 33333315, 33333317, 33333319, 33333321, 33333323, 33333325, 33333327, 33333329, 33333331, 33333333, 33333335, 33333337, + 33333339, 33333341, 33333343, 33333345, 33333347, 33333349, 33333351, 33333353, 33333355, 33333357, 33333359, 33333361, 33333363, 33333365, 33333367, + 33333369, 33333371, 33333373, 33333375, 33357697, 33357699, 33357701, 33357703, 33357705, 33357707, 33357709, 33357711, 33357713, 33357715, 33357717, + 33357719, 33357721, 33357723, 33357725, 33357727, 33357729, 33357731, 33357733, 33357735, 33357737, 33357739, 33357741, 33357743, 33357745, 33357747, + 33357749, 33357751, 33357753, 33357755, 33357757, 33357759, 33357761, 33357763, 33357765, 33357767, 33357769, 33357771, 33357773, 33357775, 33357777, + 33357779, 33357781, 33357783, 33357785, 33357787, 33357789, 33357791, 33357793, 33357795, 33357797, 33357799, 33357801, 33357803, 33357805, 33357807, + 33357809, 33357811, 33357813, 33357815, 33357817, 33357819, 33357821, 33357823, 0, 33349635, 33349637, 33349639, 33349641, 33349643, 33349645, + 33349647, 33349649, 33349651, 33349653, 33349655, 33349657, 33349659, 33349661, 33349663, 33349665, 33349667, 33349669, 33349671, 33349673, 33349675, + 33349677, 33349679, 33349681, 33349683, 33349685, 33349687, 33349689, 33349691, 33349693, 33349695, 33349697, 33349699, 33349701, 33349703, 33349705, + 33349707, 33349709, 33349711, 33349713, 33349715, 33349717, 33349719, 33349721, 33349723, 33349725, 33349727, 33349729, 33349731, 33349733, 33349735, + 33349737, 33349739, 33349741, 33349743, 33349745, 33349747, 33349749, 33349751, 33349753, 33349755, 33349757, 33349759, 33374081, 33374083, 33374085, + 33374087, 33374089, 33374091, 33374093, 33374095, 33374097, 33374099, 33374101, 33374103, 33374105, 33374107, 33374109, 33374111, 33374113, 33374115, + 33374117, 33374119, 33374121, 33374123, 33374125, 33374127, 33374129, 33374131, 33374133, 33374135, 33374137, 33374139, 33374141, 33374143, 33374145, + 33374147, 33374149, 33374151, 33374153, 33374155, 33374157, 33374159, 33374161, 33374163, 33374165, 33374167, 33374169, 33374171, 33374173, 33374175, + 33374177, 33374179, 33374181, 33374183, 33374185, 33374187, 33374189, 33374191, 33374193, 33374195, 33374197, 33374199, 33374201, 33374203, 33374205, + 33374207, 0, 33366019, 33366021, 33366023, 33366025, 33366027, 33366029, 33366031, 33366033, 33366035, 33366037, 33366039, 33366041, 33366043, + 33366045, 33366047, 33366049, 33366051, 33366053, 33366055, 33366057, 33366059, 33366061, 33366063, 33366065, 33366067, 33366069, 33366071, 33366073, + 33366075, 33366077, 33366079, 33366081, 33366083, 33366085, 33366087, 33366089, 33366091, 33366093, 33366095, 33366097, 33366099, 33366101, 33366103, + 33366105, 33366107, 33366109, 33366111, 33366113, 33366115, 33366117, 33366119, 33366121, 33366123, 33366125, 33366127, 33366129, 33366131, 33366133, + 33366135, 33366137, 33366139, 33366141, 33366143, 33390465, 33390467, 33390469, 33390471, 33390473, 33390475, 33390477, 33390479, 33390481, 33390483, + 33390485, 33390487, 33390489, 33390491, 33390493, 33390495, 33390497, 33390499, 33390501, 33390503, 33390505, 33390507, 33390509, 33390511, 33390513, + 33390515, 33390517, 33390519, 33390521, 33390523, 33390525, 33390527, 33390529, 33390531, 33390533, 33390535, 33390537, 33390539, 33390541, 33390543, + 33390545, 33390547, 33390549, 33390551, 33390553, 33390555, 33390557, 33390559, 33390561, 33390563, 33390565, 33390567, 33390569, 33390571, 33390573, + 33390575, 33390577, 33390579, 33390581, 33390583, 33390585, 33390587, 33390589, 33390591, 0, 33382403, 33382405, 33382407, 33382409, 33382411, + 33382413, 33382415, 33382417, 33382419, 33382421, 33382423, 33382425, 33382427, 33382429, 33382431, 33382433, 33382435, 33382437, 33382439, 33382441, + 33382443, 33382445, 33382447, 33382449, 33382451, 33382453, 33382455, 33382457, 33382459, 33382461, 33382463, 33382465, 33382467, 33382469, 33382471, + 33382473, 33382475, 33382477, 33382479, 33382481, 33382483, 33382485, 33382487, 33382489, 33382491, 33382493, 33382495, 33382497, 33382499, 33382501, + 33382503, 33382505, 33382507, 33382509, 33382511, 33382513, 33382515, 33382517, 33382519, 33382521, 33382523, 33382525, 33382527, 33406849, 33406851, + 33406853, 33406855, 33406857, 33406859, 33406861, 33406863, 33406865, 33406867, 33406869, 33406871, 33406873, 33406875, 33406877, 33406879, 33406881, + 33406883, 33406885, 33406887, 33406889, 33406891, 33406893, 33406895, 33406897, 33406899, 33406901, 33406903, 33406905, 33406907, 33406909, 33406911, + 33406913, 33406915, 33406917, 33406919, 33406921, 33406923, 33406925, 33406927, 33406929, 33406931, 33406933, 33406935, 33406937, 33406939, 33406941, + 33406943, 33406945, 33406947, 33406949, 33406951, 33406953, 33406955, 33406957, 33406959, 33406961, 33406963, 33406965, 33406967, 33406969, 33406971, + 33406973, 33406975, 0, 33398787, 33398789, 33398791, 33398793, 33398795, 33398797, 33398799, 33398801, 33398803, 33398805, 33398807, 33398809, + 33398811, 33398813, 33398815, 33398817, 33398819, 33398821, 33398823, 33398825, 33398827, 33398829, 33398831, 33398833, 33398835, 33398837, 33398839, + 33398841, 33398843, 33398845, 33398847, 33398849, 33398851, 33398853, 33398855, 33398857, 33398859, 33398861, 33398863, 33398865, 33398867, 33398869, + 33398871, 33398873, 33398875, 33398877, 33398879, 33398881, 33398883, 33398885, 33398887, 33398889, 33398891, 33398893, 33398895, 33398897, 33398899, + 33398901, 33398903, 33398905, 33398907, 33398909, 33398911, 33423233, 33423235, 33423237, 33423239, 33423241, 33423243, 33423245, 33423247, 33423249, + 33423251, 33423253, 33423255, 33423257, 33423259, 33423261, 33423263, 33423265, 33423267, 33423269, 33423271, 33423273, 33423275, 33423277, 33423279, + 33423281, 33423283, 33423285, 33423287, 33423289, 33423291, 33423293, 33423295, 33423297, 33423299, 33423301, 33423303, 33423305, 33423307, 33423309, + 33423311, 33423313, 33423315, 33423317, 33423319, 33423321, 33423323, 33423325, 33423327, 33423329, 33423331, 33423333, 33423335, 33423337, 33423339, + 33423341, 33423343, 33423345, 33423347, 33423349, 33423351, 33423353, 33423355, 33423357, 33423359, 0, 33415171, 33415173, 33415175, 33415177, + 33415179, 33415181, 33415183, 33415185, 33415187, 33415189, 33415191, 33415193, 33415195, 33415197, 33415199, 33415201, 33415203, 33415205, 33415207, + 33415209, 33415211, 33415213, 33415215, 33415217, 33415219, 33415221, 33415223, 33415225, 33415227, 33415229, 33415231, 33415233, 33415235, 33415237, + 33415239, 33415241, 33415243, 33415245, 33415247, 33415249, 33415251, 33415253, 33415255, 33415257, 33415259, 33415261, 33415263, 33415265, 33415267, + 33415269, 33415271, 33415273, 33415275, 33415277, 33415279, 33415281, 33415283, 33415285, 33415287, 33415289, 33415291, 33415293, 33415295, 33439617, + 33439619, 33439621, 33439623, 33439625, 33439627, 33439629, 33439631, 33439633, 33439635, 33439637, 33439639, 33439641, 33439643, 33439645, 33439647, + 33439649, 33439651, 33439653, 33439655, 33439657, 33439659, 33439661, 33439663, 33439665, 33439667, 33439669, 33439671, 33439673, 33439675, 33439677, + 33439679, 33439681, 33439683, 33439685, 33439687, 33439689, 33439691, 33439693, 33439695, 33439697, 33439699, 33439701, 33439703, 33439705, 33439707, + 33439709, 33439711, 33439713, 33439715, 33439717, 33439719, 33439721, 33439723, 33439725, 33439727, 33439729, 33439731, 33439733, 33439735, 33439737, + 33439739, 33439741, 33439743, 0, 33431555, 33431557, 33431559, 33431561, 33431563, 33431565, 33431567, 33431569, 33431571, 33431573, 33431575, + 33431577, 33431579, 33431581, 33431583, 33431585, 33431587, 33431589, 33431591, 33431593, 33431595, 33431597, 33431599, 33431601, 33431603, 33431605, + 33431607, 33431609, 33431611, 33431613, 33431615, 33431617, 33431619, 33431621, 33431623, 33431625, 33431627, 33431629, 33431631, 33431633, 33431635, + 33431637, 33431639, 33431641, 33431643, 33431645, 33431647, 33431649, 33431651, 33431653, 33431655, 33431657, 33431659, 33431661, 33431663, 33431665, + 33431667, 33431669, 33431671, 33431673, 33431675, 33431677, 33431679, 33456001, 33456003, 33456005, 33456007, 33456009, 33456011, 33456013, 33456015, + 33456017, 33456019, 33456021, 33456023, 33456025, 33456027, 33456029, 33456031, 33456033, 33456035, 33456037, 33456039, 33456041, 33456043, 33456045, + 33456047, 33456049, 33456051, 33456053, 33456055, 33456057, 33456059, 33456061, 33456063, 33456065, 33456067, 33456069, 33456071, 33456073, 33456075, + 33456077, 33456079, 33456081, 33456083, 33456085, 33456087, 33456089, 33456091, 33456093, 33456095, 33456097, 33456099, 33456101, 33456103, 33456105, + 33456107, 33456109, 33456111, 33456113, 33456115, 33456117, 33456119, 33456121, 33456123, 33456125, 33456127, 0, 33447939, 33447941, 33447943, + 33447945, 33447947, 33447949, 33447951, 33447953, 33447955, 33447957, 33447959, 33447961, 33447963, 33447965, 33447967, 33447969, 33447971, 33447973, + 33447975, 33447977, 33447979, 33447981, 33447983, 33447985, 33447987, 33447989, 33447991, 33447993, 33447995, 33447997, 33447999, 33448001, 33448003, + 33448005, 33448007, 33448009, 33448011, 33448013, 33448015, 33448017, 33448019, 33448021, 33448023, 33448025, 33448027, 33448029, 33448031, 33448033, + 33448035, 33448037, 33448039, 33448041, 33448043, 33448045, 33448047, 33448049, 33448051, 33448053, 33448055, 33448057, 33448059, 33448061, 33448063, + 33472385, 33472387, 33472389, 33472391, 33472393, 33472395, 33472397, 33472399, 33472401, 33472403, 33472405, 33472407, 33472409, 33472411, 33472413, + 33472415, 33472417, 33472419, 33472421, 33472423, 33472425, 33472427, 33472429, 33472431, 33472433, 33472435, 33472437, 33472439, 33472441, 33472443, + 33472445, 33472447, 33472449, 33472451, 33472453, 33472455, 33472457, 33472459, 33472461, 33472463, 33472465, 33472467, 33472469, 33472471, 33472473, + 33472475, 33472477, 33472479, 33472481, 33472483, 33472485, 33472487, 33472489, 33472491, 33472493, 33472495, 33472497, 33472499, 33472501, 33472503, + 33472505, 33472507, 33472509, 33472511, 0, 33464323, 33464325, 33464327, 33464329, 33464331, 33464333, 33464335, 33464337, 33464339, 33464341, + 33464343, 33464345, 33464347, 33464349, 33464351, 33464353, 33464355, 33464357, 33464359, 33464361, 33464363, 33464365, 33464367, 33464369, 33464371, + 33464373, 33464375, 33464377, 33464379, 33464381, 33464383, 33464385, 33464387, 33464389, 33464391, 33464393, 33464395, 33464397, 33464399, 33464401, + 33464403, 33464405, 33464407, 33464409, 33464411, 33464413, 33464415, 33464417, 33464419, 33464421, 33464423, 33464425, 33464427, 33464429, 33464431, + 33464433, 33464435, 33464437, 33464439, 33464441, 33464443, 33464445, 33464447, 33488769, 33488771, 33488773, 33488775, 33488777, 33488779, 33488781, + 33488783, 33488785, 33488787, 33488789, 33488791, 33488793, 33488795, 33488797, 33488799, 33488801, 33488803, 33488805, 33488807, 33488809, 33488811, + 33488813, 33488815, 33488817, 33488819, 33488821, 33488823, 33488825, 33488827, 33488829, 33488831, 33488833, 33488835, 33488837, 33488839, 33488841, + 33488843, 33488845, 33488847, 33488849, 33488851, 33488853, 33488855, 33488857, 33488859, 33488861, 33488863, 33488865, 33488867, 33488869, 33488871, + 33488873, 33488875, 33488877, 33488879, 33488881, 33488883, 33488885, 33488887, 33488889, 33488891, 33488893, 33488895, 0, 33480707, 33480709, + 33480711, 33480713, 33480715, 33480717, 33480719, 33480721, 33480723, 33480725, 33480727, 33480729, 33480731, 33480733, 33480735, 33480737, 33480739, + 33480741, 33480743, 33480745, 33480747, 33480749, 33480751, 33480753, 33480755, 33480757, 33480759, 33480761, 33480763, 33480765, 33480767, 33480769, + 33480771, 33480773, 33480775, 33480777, 33480779, 33480781, 33480783, 33480785, 33480787, 33480789, 33480791, 33480793, 33480795, 33480797, 33480799, + 33480801, 33480803, 33480805, 33480807, 33480809, 33480811, 33480813, 33480815, 33480817, 33480819, 33480821, 33480823, 33480825, 33480827, 33480829, + 33480831, 33505153, 33505155, 33505157, 33505159, 33505161, 33505163, 33505165, 33505167, 33505169, 33505171, 33505173, 33505175, 33505177, 33505179, + 33505181, 33505183, 33505185, 33505187, 33505189, 33505191, 33505193, 33505195, 33505197, 33505199, 33505201, 33505203, 33505205, 33505207, 33505209, + 33505211, 33505213, 33505215, 33505217, 33505219, 33505221, 33505223, 33505225, 33505227, 33505229, 33505231, 33505233, 33505235, 33505237, 33505239, + 33505241, 33505243, 33505245, 33505247, 33505249, 33505251, 33505253, 33505255, 33505257, 33505259, 33505261, 33505263, 33505265, 33505267, 33505269, + 33505271, 33505273, 33505275, 33505277, 33505279, 0, 33497091, 33497093, 33497095, 33497097, 33497099, 33497101, 33497103, 33497105, 33497107, + 33497109, 33497111, 33497113, 33497115, 33497117, 33497119, 33497121, 33497123, 33497125, 33497127, 33497129, 33497131, 33497133, 33497135, 33497137, + 33497139, 33497141, 33497143, 33497145, 33497147, 33497149, 33497151, 33497153, 33497155, 33497157, 33497159, 33497161, 33497163, 33497165, 33497167, + 33497169, 33497171, 33497173, 33497175, 33497177, 33497179, 33497181, 33497183, 33497185, 33497187, 33497189, 33497191, 33497193, 33497195, 33497197, + 33497199, 33497201, 33497203, 33497205, 33497207, 33497209, 33497211, 33497213, 33497215, 33521537, 33521539, 33521541, 33521543, 33521545, 33521547, + 33521549, 33521551, 33521553, 33521555, 33521557, 33521559, 33521561, 33521563, 33521565, 33521567, 33521569, 33521571, 33521573, 33521575, 33521577, + 33521579, 33521581, 33521583, 33521585, 33521587, 33521589, 33521591, 33521593, 33521595, 33521597, 33521599, 33521601, 33521603, 33521605, 33521607, + 33521609, 33521611, 33521613, 33521615, 33521617, 33521619, 33521621, 33521623, 33521625, 33521627, 33521629, 33521631, 33521633, 33521635, 33521637, + 33521639, 33521641, 33521643, 33521645, 33521647, 33521649, 33521651, 33521653, 33521655, 33521657, 33521659, 33521661, 33521663, 0, 33513475, + 33513477, 33513479, 33513481, 33513483, 33513485, 33513487, 33513489, 33513491, 33513493, 33513495, 33513497, 33513499, 33513501, 33513503, 33513505, + 33513507, 33513509, 33513511, 33513513, 33513515, 33513517, 33513519, 33513521, 33513523, 33513525, 33513527, 33513529, 33513531, 33513533, 33513535, + 33513537, 33513539, 33513541, 33513543, 33513545, 33513547, 33513549, 33513551, 33513553, 33513555, 33513557, 33513559, 33513561, 33513563, 33513565, + 33513567, 33513569, 33513571, 33513573, 33513575, 33513577, 33513579, 33513581, 33513583, 33513585, 33513587, 33513589, 33513591, 33513593, 33513595, + 33513597, 33513599, 33537921, 33537923, 33537925, 33537927, 33537929, 33537931, 33537933, 33537935, 33537937, 33537939, 33537941, 33537943, 33537945, + 33537947, 33537949, 33537951, 33537953, 33537955, 33537957, 33537959, 33537961, 33537963, 33537965, 33537967, 33537969, 33537971, 33537973, 33537975, + 33537977, 33537979, 33537981, 33537983, 33537985, 33537987, 33537989, 33537991, 33537993, 33537995, 33537997, 33537999, 33538001, 33538003, 33538005, + 33538007, 33538009, 33538011, 33538013, 33538015, 33538017, 33538019, 33538021, 33538023, 33538025, 33538027, 33538029, 33538031, 33538033, 33538035, + 33538037, 33538039, 33538041, 33538043, 33538045, 33538047, 0, 33529859, 33529861, 33529863, 33529865, 33529867, 33529869, 33529871, 33529873, + 33529875, 33529877, 33529879, 33529881, 33529883, 33529885, 33529887, 33529889, 33529891, 33529893, 33529895, 33529897, 33529899, 33529901, 33529903, + 33529905, 33529907, 33529909, 33529911, 33529913, 33529915, 33529917, 33529919, 33529921, 33529923, 33529925, 33529927, 33529929, 33529931, 33529933, + 33529935, 33529937, 33529939, 33529941, 33529943, 33529945, 33529947, 33529949, 33529951, 33529953, 33529955, 33529957, 33529959, 33529961, 33529963, + 33529965, 33529967, 33529969, 33529971, 33529973, 33529975, 33529977, 33529979, 33529981, 33529983, 33554305, 33554307, 33554309, 33554311, 33554313, + 33554315, 33554317, 33554319, 33554321, 33554323, 33554325, 33554327, 33554329, 33554331, 33554333, 33554335, 33554337, 33554339, 33554341, 33554343, + 33554345, 33554347, 33554349, 33554351, 33554353, 33554355, 33554357, 33554359, 33554361, 33554363, 33554365, 33554367, 33554369, 33554371, 33554373, + 33554375, 33554377, 33554379, 33554381, 33554383, 33554385, 33554387, 33554389, 33554391, 33554393, 33554395, 33554397, 33554399, 33554401, 33554403, + 33554405, 33554407, 33554409, 33554411, 33554413, 33554415, 33554417, 33554419, 33554421, 33554423, 33554425, 33554427, 33554429, 33554431, 0, + 33546243, 33546245, 33546247, 33546249, 33546251, 33546253, 33546255, 33546257, 33546259, 33546261, 33546263, 33546265, 33546267, 33546269, 33546271, + 33546273, 33546275, 33546277, 33546279, 33546281, 33546283, 33546285, 33546287, 33546289, 33546291, 33546293, 33546295, 33546297, 33546299, 33546301, + 33546303, 33546305, 33546307, 33546309, 33546311, 33546313, 33546315, 33546317, 33546319, 33546321, 33546323, 33546325, 33546327, 33546329, 33546331, + 33546333, 33546335, 33546337, 33546339, 33546341, 33546343, 33546345, 33546347, 33546349, 33546351, 33546353, 33546355, 33546357, 33546359, 33546361, + 33546363, 33546365, 33546367 +}; + +static const uint8 uni_mpeg4_intra_rl_len[] = +{ + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19, 19, + 18, 18, 18, 18, 17, 17, 17, 16, 15, 15, 15, 14, 14, 13, 12, 11, 13, 13, 13, 12, + 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 8, 7, 7, 7, 6, 6, + 5, 4, 3, 0, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 11, 12, 13, 14, 14, 15, 15, 15, 16, + 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 19, 18, 18, 17, 16, 15, + 13, 13, 13, 12, 11, 10, 10, 9, 8, 7, 5, 0, 5, 7, 8, 9, 10, 10, 11, 12, + 13, 13, 13, 15, 16, 17, 18, 18, 19, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 17, 16, 16, 14, 13, 11, 10, 8, 6, 0, + 6, 8, 10, 11, 13, 14, 16, 16, 17, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 22, 19, + 18, 17, 15, 11, 10, 9, 7, 0, 7, 9, 10, 11, 15, 17, 18, 19, 22, 22, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 18, 15, 11, 10, 7, 0, 7, 10, 11, 15, + 18, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 18, 15, + 11, 10, 7, 0, 7, 10, 11, 15, 18, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 21, 18, 16, 13, 10, 8, 0, 8, 10, 13, 16, 18, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 18, 16, 13, 10, 8, 0, + 8, 10, 13, 16, 18, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 19, 14, 11, 9, 0, 9, 11, 14, 19, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 17, 12, 9, 0, 9, 12, 17, 20, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 19, 13, 9, 0, 9, 13, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 19, 16, 10, 0, 10, 16, 19, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 17, 10, 0, + 10, 17, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 20, 18, 11, 0, 11, 18, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 19, 13, 0, 13, 19, 22, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 22, 19, 12, 0, 12, 19, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 14, 0, 14, 19, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 15, 0, + 15, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 20, 16, 0, 16, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 16, 0, 16, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, + 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 20, 0, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 0, 22, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, + 20, 20, 19, 18, 17, 15, 13, 13, 12, 12, 11, 10, 9, 7, 5, 0, 5, 7, 9, 10, + 11, 12, 12, 13, 13, 15, 17, 18, 19, 20, 20, 21, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 21, 19, 18, 15, + 11, 10, 7, 0, 7, 10, 11, 15, 18, 19, 21, 22, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 19, 15, 11, 7, 0, 7, 11, 15, 19, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 16, 12, 8, 0, + 8, 12, 16, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 20, 16, 12, 8, 0, 8, 12, 16, 20, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 16, 13, 8, 0, 8, 13, 16, 21, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, + 17, 13, 9, 0, 9, 13, 17, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 9, 0, 9, 16, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, + 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, + 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 20, 12, 0, 12, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, + 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 14, 0, 14, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, + 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, + 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 21, 0, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 0, 21, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 0, + 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 22, 0, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 0, 22, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 22, 0, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30 +}; + +static const uint32 uni_mpeg4_inter_rl_bits[] = +{ + 31473537, 31473539, 31473541, 31473543, 31473545, 31473547, 31473549, 31473551, 31473553, 31473555, 31473557, 31473559, 31473561, 31473563, 31473565, 31473567, + 31473569, 31473571, 31473573, 31473575, 31473577, 31473579, 31473581, 31473583, 31473585, 31473587, 31473589, 31473591, 31473593, 31473595, 31473597, + 31473599, 31473601, 31473603, 31473605, 31473607, 31473609, 31473611, 31473613, 31473615, 24641, 24589, 24591, 12353, 12355, 6217, + 6219, 3135, 1583, 811, 223, 53, 65, 13, 15, 65, 67, 73, 75, 63, 47, + 43, 31, 5, 0, 4, 30, 42, 46, 62, 74, 72, 66, 64, 14, 12, + 64, 52, 222, 810, 1582, 3134, 6218, 6216, 12354, 12352, 24590, 24588, 24640, 31465523, 31465525, + 31465527, 31465529, 31465531, 31465533, 31465535, 31465537, 31465539, 31465541, 31465543, 31465545, 31465547, 31465549, 31465551, 31465553, 31465555, + 31465557, 31465559, 31465561, 31465563, 31465565, 31465567, 31465569, 31465571, 31465573, 31465575, 31465577, 31465579, 31465581, 31465583, 31465585, + 31465587, 31465589, 31465591, 31465593, 31465595, 31465597, 31465599, 31489921, 31489923, 31489925, 31489927, 31489929, 31489931, 31489933, 31489935, + 31489937, 31489939, 31489941, 31489943, 31489945, 31489947, 31489949, 31489951, 31489953, 31489955, 31489957, 31489959, 31489961, 31489963, 31489965, + 31489967, 31489969, 31489971, 31489973, 31489975, 31489977, 31489979, 31489981, 31489983, 31489985, 31489987, 31489989, 31489991, 31489993, 31489995, + 31489997, 31489999, 31490001, 31490003, 31490005, 31490007, 31490009, 31490011, 31490013, 31490015, 31490017, 31490019, 31490021, 31490023, 49313, + 24643, 12319, 3133, 809, 109, 161, 67, 31, 61, 41, 13, 0, 12, 40, 60, + 30, 66, 160, 108, 808, 3132, 12318, 24642, 49312, 31481883, 31481885, 31481887, 31481889, 31481891, 31481893, + 31481895, 31481897, 31481899, 31481901, 31481903, 31481905, 31481907, 31481909, 31481911, 31481913, 31481915, 31481917, 31481919, 31481921, 31481923, + 31481925, 31481927, 31481929, 31481931, 31481933, 31481935, 31481937, 31481939, 31481941, 31481943, 31481945, 31481947, 31481949, 31481951, 31481953, + 31481955, 31481957, 31481959, 31481961, 31481963, 31481965, 31481967, 31481969, 31481971, 31481973, 31481975, 31481977, 31481979, 31481981, 31481983, + 31506305, 31506307, 31506309, 31506311, 31506313, 31506315, 31506317, 31506319, 31506321, 31506323, 31506325, 31506327, 31506329, 31506331, 31506333, + 31506335, 31506337, 31506339, 31506341, 31506343, 31506345, 31506347, 31506349, 31506351, 31506353, 31506355, 31506357, 31506359, 31506361, 31506363, + 31506365, 31506367, 31506369, 31506371, 31506373, 31506375, 31506377, 31506379, 31506381, 31506383, 31506385, 31506387, 31506389, 31506391, 31506393, + 31506395, 31506397, 31506399, 31506401, 31506403, 31506405, 31506407, 31506409, 31506411, 31506413, 31506415, 49315, 12317, 3131, 221, + 163, 29, 59, 29, 0, 28, 58, 28, 162, 220, 3130, 12316, 49314, 31498259, 31498261, + 31498263, 31498265, 31498267, 31498269, 31498271, 31498273, 31498275, 31498277, 31498279, 31498281, 31498283, 31498285, 31498287, 31498289, 31498291, + 31498293, 31498295, 31498297, 31498299, 31498301, 31498303, 31498305, 31498307, 31498309, 31498311, 31498313, 31498315, 31498317, 31498319, 31498321, + 31498323, 31498325, 31498327, 31498329, 31498331, 31498333, 31498335, 31498337, 31498339, 31498341, 31498343, 31498345, 31498347, 31498349, 31498351, + 31498353, 31498355, 31498357, 31498359, 31498361, 31498363, 31498365, 31498367, 31522689, 31522691, 31522693, 31522695, 31522697, 31522699, 31522701, + 31522703, 31522705, 31522707, 31522709, 31522711, 31522713, 31522715, 31522717, 31522719, 31522721, 31522723, 31522725, 31522727, 31522729, 31522731, + 31522733, 31522735, 31522737, 31522739, 31522741, 31522743, 31522745, 31522747, 31522749, 31522751, 31522753, 31522755, 31522757, 31522759, 31522761, + 31522763, 31522765, 31522767, 31522769, 31522771, 31522773, 31522775, 31522777, 31522779, 31522781, 31522783, 31522785, 31522787, 31522789, 31522791, + 31522793, 31522795, 31522797, 31522799, 31522801, 31522803, 12315, 6215, 411, 27, 71, 27, 0, 26, 70, + 26, 410, 6214, 12314, 31514639, 31514641, 31514643, 31514645, 31514647, 31514649, 31514651, 31514653, 31514655, 31514657, 31514659, + 31514661, 31514663, 31514665, 31514667, 31514669, 31514671, 31514673, 31514675, 31514677, 31514679, 31514681, 31514683, 31514685, 31514687, 31514689, + 31514691, 31514693, 31514695, 31514697, 31514699, 31514701, 31514703, 31514705, 31514707, 31514709, 31514711, 31514713, 31514715, 31514717, 31514719, + 31514721, 31514723, 31514725, 31514727, 31514729, 31514731, 31514733, 31514735, 31514737, 31514739, 31514741, 31514743, 31514745, 31514747, 31514749, + 31514751, 31539073, 31539075, 31539077, 31539079, 31539081, 31539083, 31539085, 31539087, 31539089, 31539091, 31539093, 31539095, 31539097, 31539099, + 31539101, 31539103, 31539105, 31539107, 31539109, 31539111, 31539113, 31539115, 31539117, 31539119, 31539121, 31539123, 31539125, 31539127, 31539129, + 31539131, 31539133, 31539135, 31539137, 31539139, 31539141, 31539143, 31539145, 31539147, 31539149, 31539151, 31539153, 31539155, 31539157, 31539159, + 31539161, 31539163, 31539165, 31539167, 31539169, 31539171, 31539173, 31539175, 31539177, 31539179, 31539181, 31539183, 31539185, 31539187, 49317, + 6213, 409, 165, 69, 25, 0, 24, 68, 164, 408, 6212, 49316, 31531023, 31531025, 31531027, + 31531029, 31531031, 31531033, 31531035, 31531037, 31531039, 31531041, 31531043, 31531045, 31531047, 31531049, 31531051, 31531053, 31531055, 31531057, + 31531059, 31531061, 31531063, 31531065, 31531067, 31531069, 31531071, 31531073, 31531075, 31531077, 31531079, 31531081, 31531083, 31531085, 31531087, + 31531089, 31531091, 31531093, 31531095, 31531097, 31531099, 31531101, 31531103, 31531105, 31531107, 31531109, 31531111, 31531113, 31531115, 31531117, + 31531119, 31531121, 31531123, 31531125, 31531127, 31531129, 31531131, 31531133, 31531135, 31555457, 31555459, 31555461, 31555463, 31555465, 31555467, + 31555469, 31555471, 31555473, 31555475, 31555477, 31555479, 31555481, 31555483, 31555485, 31555487, 31555489, 31555491, 31555493, 31555495, 31555497, + 31555499, 31555501, 31555503, 31555505, 31555507, 31555509, 31555511, 31555513, 31555515, 31555517, 31555519, 31555521, 31555523, 31555525, 31555527, + 31555529, 31555531, 31555533, 31555535, 31555537, 31555539, 31555541, 31555543, 31555545, 31555547, 31555549, 31555551, 31555553, 31555555, 31555557, + 31555559, 31555561, 31555563, 31555565, 31555567, 31555569, 31555571, 49319, 12313, 407, 167, 25, 23, 0, 22, + 24, 166, 406, 12312, 49318, 31547407, 31547409, 31547411, 31547413, 31547415, 31547417, 31547419, 31547421, 31547423, 31547425, + 31547427, 31547429, 31547431, 31547433, 31547435, 31547437, 31547439, 31547441, 31547443, 31547445, 31547447, 31547449, 31547451, 31547453, 31547455, + 31547457, 31547459, 31547461, 31547463, 31547465, 31547467, 31547469, 31547471, 31547473, 31547475, 31547477, 31547479, 31547481, 31547483, 31547485, + 31547487, 31547489, 31547491, 31547493, 31547495, 31547497, 31547499, 31547501, 31547503, 31547505, 31547507, 31547509, 31547511, 31547513, 31547515, + 31547517, 31547519, 31571841, 31571843, 31571845, 31571847, 31571849, 31571851, 31571853, 31571855, 31571857, 31571859, 31571861, 31571863, 31571865, + 31571867, 31571869, 31571871, 31571873, 31571875, 31571877, 31571879, 31571881, 31571883, 31571885, 31571887, 31571889, 31571891, 31571893, 31571895, + 31571897, 31571899, 31571901, 31571903, 31571905, 31571907, 31571909, 31571911, 31571913, 31571915, 31571917, 31571919, 31571921, 31571923, 31571925, + 31571927, 31571929, 31571931, 31571933, 31571935, 31571937, 31571939, 31571941, 31571943, 31571945, 31571947, 31571949, 31571951, 31571953, 31571955, + 49321, 12311, 807, 169, 23, 39, 0, 38, 22, 168, 806, 12310, 49320, 31563791, 31563793, + 31563795, 31563797, 31563799, 31563801, 31563803, 31563805, 31563807, 31563809, 31563811, 31563813, 31563815, 31563817, 31563819, 31563821, 31563823, + 31563825, 31563827, 31563829, 31563831, 31563833, 31563835, 31563837, 31563839, 31563841, 31563843, 31563845, 31563847, 31563849, 31563851, 31563853, + 31563855, 31563857, 31563859, 31563861, 31563863, 31563865, 31563867, 31563869, 31563871, 31563873, 31563875, 31563877, 31563879, 31563881, 31563883, + 31563885, 31563887, 31563889, 31563891, 31563893, 31563895, 31563897, 31563899, 31563901, 31563903, 31588225, 31588227, 31588229, 31588231, 31588233, + 31588235, 31588237, 31588239, 31588241, 31588243, 31588245, 31588247, 31588249, 31588251, 31588253, 31588255, 31588257, 31588259, 31588261, 31588263, + 31588265, 31588267, 31588269, 31588271, 31588273, 31588275, 31588277, 31588279, 31588281, 31588283, 31588285, 31588287, 31588289, 31588291, 31588293, + 31588295, 31588297, 31588299, 31588301, 31588303, 31588305, 31588307, 31588309, 31588311, 31588313, 31588315, 31588317, 31588319, 31588321, 31588323, + 31588325, 31588327, 31588329, 31588331, 31588333, 31588335, 31588337, 31588339, 31588341, 31588343, 12309, 805, 21, 37, 0, + 36, 20, 804, 12308, 31580171, 31580173, 31580175, 31580177, 31580179, 31580181, 31580183, 31580185, 31580187, 31580189, 31580191, + 31580193, 31580195, 31580197, 31580199, 31580201, 31580203, 31580205, 31580207, 31580209, 31580211, 31580213, 31580215, 31580217, 31580219, 31580221, + 31580223, 31580225, 31580227, 31580229, 31580231, 31580233, 31580235, 31580237, 31580239, 31580241, 31580243, 31580245, 31580247, 31580249, 31580251, + 31580253, 31580255, 31580257, 31580259, 31580261, 31580263, 31580265, 31580267, 31580269, 31580271, 31580273, 31580275, 31580277, 31580279, 31580281, + 31580283, 31580285, 31580287, 31604609, 31604611, 31604613, 31604615, 31604617, 31604619, 31604621, 31604623, 31604625, 31604627, 31604629, 31604631, + 31604633, 31604635, 31604637, 31604639, 31604641, 31604643, 31604645, 31604647, 31604649, 31604651, 31604653, 31604655, 31604657, 31604659, 31604661, + 31604663, 31604665, 31604667, 31604669, 31604671, 31604673, 31604675, 31604677, 31604679, 31604681, 31604683, 31604685, 31604687, 31604689, 31604691, + 31604693, 31604695, 31604697, 31604699, 31604701, 31604703, 31604705, 31604707, 31604709, 31604711, 31604713, 31604715, 31604717, 31604719, 31604721, + 31604723, 31604725, 31604727, 12307, 803, 19, 35, 0, 34, 18, 802, 12306, 31596555, 31596557, 31596559, + 31596561, 31596563, 31596565, 31596567, 31596569, 31596571, 31596573, 31596575, 31596577, 31596579, 31596581, 31596583, 31596585, 31596587, 31596589, + 31596591, 31596593, 31596595, 31596597, 31596599, 31596601, 31596603, 31596605, 31596607, 31596609, 31596611, 31596613, 31596615, 31596617, 31596619, + 31596621, 31596623, 31596625, 31596627, 31596629, 31596631, 31596633, 31596635, 31596637, 31596639, 31596641, 31596643, 31596645, 31596647, 31596649, + 31596651, 31596653, 31596655, 31596657, 31596659, 31596661, 31596663, 31596665, 31596667, 31596669, 31596671, 31620993, 31620995, 31620997, 31620999, + 31621001, 31621003, 31621005, 31621007, 31621009, 31621011, 31621013, 31621015, 31621017, 31621019, 31621021, 31621023, 31621025, 31621027, 31621029, + 31621031, 31621033, 31621035, 31621037, 31621039, 31621041, 31621043, 31621045, 31621047, 31621049, 31621051, 31621053, 31621055, 31621057, 31621059, + 31621061, 31621063, 31621065, 31621067, 31621069, 31621071, 31621073, 31621075, 31621077, 31621079, 31621081, 31621083, 31621085, 31621087, 31621089, + 31621091, 31621093, 31621095, 31621097, 31621099, 31621101, 31621103, 31621105, 31621107, 31621109, 31621111, 12305, 801, 17, 33, + 0, 32, 16, 800, 12304, 31612939, 31612941, 31612943, 31612945, 31612947, 31612949, 31612951, 31612953, 31612955, 31612957, + 31612959, 31612961, 31612963, 31612965, 31612967, 31612969, 31612971, 31612973, 31612975, 31612977, 31612979, 31612981, 31612983, 31612985, 31612987, + 31612989, 31612991, 31612993, 31612995, 31612997, 31612999, 31613001, 31613003, 31613005, 31613007, 31613009, 31613011, 31613013, 31613015, 31613017, + 31613019, 31613021, 31613023, 31613025, 31613027, 31613029, 31613031, 31613033, 31613035, 31613037, 31613039, 31613041, 31613043, 31613045, 31613047, + 31613049, 31613051, 31613053, 31613055, 31637377, 31637379, 31637381, 31637383, 31637385, 31637387, 31637389, 31637391, 31637393, 31637395, 31637397, + 31637399, 31637401, 31637403, 31637405, 31637407, 31637409, 31637411, 31637413, 31637415, 31637417, 31637419, 31637421, 31637423, 31637425, 31637427, + 31637429, 31637431, 31637433, 31637435, 31637437, 31637439, 31637441, 31637443, 31637445, 31637447, 31637449, 31637451, 31637453, 31637455, 31637457, + 31637459, 31637461, 31637463, 31637465, 31637467, 31637469, 31637471, 31637473, 31637475, 31637477, 31637479, 31637481, 31637483, 31637485, 31637487, + 31637489, 31637491, 31637493, 31637495, 49323, 1581, 171, 45, 0, 44, 170, 1580, 49322, 31629323, 31629325, + 31629327, 31629329, 31629331, 31629333, 31629335, 31629337, 31629339, 31629341, 31629343, 31629345, 31629347, 31629349, 31629351, 31629353, 31629355, + 31629357, 31629359, 31629361, 31629363, 31629365, 31629367, 31629369, 31629371, 31629373, 31629375, 31629377, 31629379, 31629381, 31629383, 31629385, + 31629387, 31629389, 31629391, 31629393, 31629395, 31629397, 31629399, 31629401, 31629403, 31629405, 31629407, 31629409, 31629411, 31629413, 31629415, + 31629417, 31629419, 31629421, 31629423, 31629425, 31629427, 31629429, 31629431, 31629433, 31629435, 31629437, 31629439, 31653761, 31653763, 31653765, + 31653767, 31653769, 31653771, 31653773, 31653775, 31653777, 31653779, 31653781, 31653783, 31653785, 31653787, 31653789, 31653791, 31653793, 31653795, + 31653797, 31653799, 31653801, 31653803, 31653805, 31653807, 31653809, 31653811, 31653813, 31653815, 31653817, 31653819, 31653821, 31653823, 31653825, + 31653827, 31653829, 31653831, 31653833, 31653835, 31653837, 31653839, 31653841, 31653843, 31653845, 31653847, 31653849, 31653851, 31653853, 31653855, + 31653857, 31653859, 31653861, 31653863, 31653865, 31653867, 31653869, 31653871, 31653873, 31653875, 31653877, 31653879, 31653881, 114853, 479, + 43, 0, 42, 478, 114852, 31645705, 31645707, 31645709, 31645711, 31645713, 31645715, 31645717, 31645719, 31645721, 31645723, + 31645725, 31645727, 31645729, 31645731, 31645733, 31645735, 31645737, 31645739, 31645741, 31645743, 31645745, 31645747, 31645749, 31645751, 31645753, + 31645755, 31645757, 31645759, 31645761, 31645763, 31645765, 31645767, 31645769, 31645771, 31645773, 31645775, 31645777, 31645779, 31645781, 31645783, + 31645785, 31645787, 31645789, 31645791, 31645793, 31645795, 31645797, 31645799, 31645801, 31645803, 31645805, 31645807, 31645809, 31645811, 31645813, + 31645815, 31645817, 31645819, 31645821, 31645823, 31670145, 31670147, 31670149, 31670151, 31670153, 31670155, 31670157, 31670159, 31670161, 31670163, + 31670165, 31670167, 31670169, 31670171, 31670173, 31670175, 31670177, 31670179, 31670181, 31670183, 31670185, 31670187, 31670189, 31670191, 31670193, + 31670195, 31670197, 31670199, 31670201, 31670203, 31670205, 31670207, 31670209, 31670211, 31670213, 31670215, 31670217, 31670219, 31670221, 31670223, + 31670225, 31670227, 31670229, 31670231, 31670233, 31670235, 31670237, 31670239, 31670241, 31670243, 31670245, 31670247, 31670249, 31670251, 31670253, + 31670255, 31670257, 31670259, 31670261, 31670263, 31670265, 114855, 1577, 41, 0, 40, 1576, 114854, 31662089, 31662091, + 31662093, 31662095, 31662097, 31662099, 31662101, 31662103, 31662105, 31662107, 31662109, 31662111, 31662113, 31662115, 31662117, 31662119, 31662121, + 31662123, 31662125, 31662127, 31662129, 31662131, 31662133, 31662135, 31662137, 31662139, 31662141, 31662143, 31662145, 31662147, 31662149, 31662151, + 31662153, 31662155, 31662157, 31662159, 31662161, 31662163, 31662165, 31662167, 31662169, 31662171, 31662173, 31662175, 31662177, 31662179, 31662181, + 31662183, 31662185, 31662187, 31662189, 31662191, 31662193, 31662195, 31662197, 31662199, 31662201, 31662203, 31662205, 31662207, 31686529, 31686531, + 31686533, 31686535, 31686537, 31686539, 31686541, 31686543, 31686545, 31686547, 31686549, 31686551, 31686553, 31686555, 31686557, 31686559, 31686561, + 31686563, 31686565, 31686567, 31686569, 31686571, 31686573, 31686575, 31686577, 31686579, 31686581, 31686583, 31686585, 31686587, 31686589, 31686591, + 31686593, 31686595, 31686597, 31686599, 31686601, 31686603, 31686605, 31686607, 31686609, 31686611, 31686613, 31686615, 31686617, 31686619, 31686621, + 31686623, 31686625, 31686627, 31686629, 31686631, 31686633, 31686635, 31686637, 31686639, 31686641, 31686643, 31686645, 31686647, 31686649, 114857, + 3129, 57, 0, 56, 3128, 114856, 31678473, 31678475, 31678477, 31678479, 31678481, 31678483, 31678485, 31678487, 31678489, + 31678491, 31678493, 31678495, 31678497, 31678499, 31678501, 31678503, 31678505, 31678507, 31678509, 31678511, 31678513, 31678515, 31678517, 31678519, + 31678521, 31678523, 31678525, 31678527, 31678529, 31678531, 31678533, 31678535, 31678537, 31678539, 31678541, 31678543, 31678545, 31678547, 31678549, + 31678551, 31678553, 31678555, 31678557, 31678559, 31678561, 31678563, 31678565, 31678567, 31678569, 31678571, 31678573, 31678575, 31678577, 31678579, + 31678581, 31678583, 31678585, 31678587, 31678589, 31678591, 31702913, 31702915, 31702917, 31702919, 31702921, 31702923, 31702925, 31702927, 31702929, + 31702931, 31702933, 31702935, 31702937, 31702939, 31702941, 31702943, 31702945, 31702947, 31702949, 31702951, 31702953, 31702955, 31702957, 31702959, + 31702961, 31702963, 31702965, 31702967, 31702969, 31702971, 31702973, 31702975, 31702977, 31702979, 31702981, 31702983, 31702985, 31702987, 31702989, + 31702991, 31702993, 31702995, 31702997, 31702999, 31703001, 31703003, 31703005, 31703007, 31703009, 31703011, 31703013, 31703015, 31703017, 31703019, + 31703021, 31703023, 31703025, 31703027, 31703029, 31703031, 31703033, 31703035, 3127, 55, 0, 54, 3126, 31694855, 31694857, + 31694859, 31694861, 31694863, 31694865, 31694867, 31694869, 31694871, 31694873, 31694875, 31694877, 31694879, 31694881, 31694883, 31694885, 31694887, + 31694889, 31694891, 31694893, 31694895, 31694897, 31694899, 31694901, 31694903, 31694905, 31694907, 31694909, 31694911, 31694913, 31694915, 31694917, + 31694919, 31694921, 31694923, 31694925, 31694927, 31694929, 31694931, 31694933, 31694935, 31694937, 31694939, 31694941, 31694943, 31694945, 31694947, + 31694949, 31694951, 31694953, 31694955, 31694957, 31694959, 31694961, 31694963, 31694965, 31694967, 31694969, 31694971, 31694973, 31694975, 31719297, + 31719299, 31719301, 31719303, 31719305, 31719307, 31719309, 31719311, 31719313, 31719315, 31719317, 31719319, 31719321, 31719323, 31719325, 31719327, + 31719329, 31719331, 31719333, 31719335, 31719337, 31719339, 31719341, 31719343, 31719345, 31719347, 31719349, 31719351, 31719353, 31719355, 31719357, + 31719359, 31719361, 31719363, 31719365, 31719367, 31719369, 31719371, 31719373, 31719375, 31719377, 31719379, 31719381, 31719383, 31719385, 31719387, + 31719389, 31719391, 31719393, 31719395, 31719397, 31719399, 31719401, 31719403, 31719405, 31719407, 31719409, 31719411, 31719413, 31719415, 31719417, + 31719419, 6211, 67, 0, 66, 6210, 31711239, 31711241, 31711243, 31711245, 31711247, 31711249, 31711251, 31711253, 31711255, + 31711257, 31711259, 31711261, 31711263, 31711265, 31711267, 31711269, 31711271, 31711273, 31711275, 31711277, 31711279, 31711281, 31711283, 31711285, + 31711287, 31711289, 31711291, 31711293, 31711295, 31711297, 31711299, 31711301, 31711303, 31711305, 31711307, 31711309, 31711311, 31711313, 31711315, + 31711317, 31711319, 31711321, 31711323, 31711325, 31711327, 31711329, 31711331, 31711333, 31711335, 31711337, 31711339, 31711341, 31711343, 31711345, + 31711347, 31711349, 31711351, 31711353, 31711355, 31711357, 31711359, 31735681, 31735683, 31735685, 31735687, 31735689, 31735691, 31735693, 31735695, + 31735697, 31735699, 31735701, 31735703, 31735705, 31735707, 31735709, 31735711, 31735713, 31735715, 31735717, 31735719, 31735721, 31735723, 31735725, + 31735727, 31735729, 31735731, 31735733, 31735735, 31735737, 31735739, 31735741, 31735743, 31735745, 31735747, 31735749, 31735751, 31735753, 31735755, + 31735757, 31735759, 31735761, 31735763, 31735765, 31735767, 31735769, 31735771, 31735773, 31735775, 31735777, 31735779, 31735781, 31735783, 31735785, + 31735787, 31735789, 31735791, 31735793, 31735795, 31735797, 31735799, 31735801, 31735803, 6209, 65, 0, 64, 6208, 31727623, + 31727625, 31727627, 31727629, 31727631, 31727633, 31727635, 31727637, 31727639, 31727641, 31727643, 31727645, 31727647, 31727649, 31727651, 31727653, + 31727655, 31727657, 31727659, 31727661, 31727663, 31727665, 31727667, 31727669, 31727671, 31727673, 31727675, 31727677, 31727679, 31727681, 31727683, + 31727685, 31727687, 31727689, 31727691, 31727693, 31727695, 31727697, 31727699, 31727701, 31727703, 31727705, 31727707, 31727709, 31727711, 31727713, + 31727715, 31727717, 31727719, 31727721, 31727723, 31727725, 31727727, 31727729, 31727731, 31727733, 31727735, 31727737, 31727739, 31727741, 31727743, + 31752065, 31752067, 31752069, 31752071, 31752073, 31752075, 31752077, 31752079, 31752081, 31752083, 31752085, 31752087, 31752089, 31752091, 31752093, + 31752095, 31752097, 31752099, 31752101, 31752103, 31752105, 31752107, 31752109, 31752111, 31752113, 31752115, 31752117, 31752119, 31752121, 31752123, + 31752125, 31752127, 31752129, 31752131, 31752133, 31752135, 31752137, 31752139, 31752141, 31752143, 31752145, 31752147, 31752149, 31752151, 31752153, + 31752155, 31752157, 31752159, 31752161, 31752163, 31752165, 31752167, 31752169, 31752171, 31752173, 31752175, 31752177, 31752179, 31752181, 31752183, + 31752185, 31752187, 6207, 63, 0, 62, 6206, 31744007, 31744009, 31744011, 31744013, 31744015, 31744017, 31744019, 31744021, + 31744023, 31744025, 31744027, 31744029, 31744031, 31744033, 31744035, 31744037, 31744039, 31744041, 31744043, 31744045, 31744047, 31744049, 31744051, + 31744053, 31744055, 31744057, 31744059, 31744061, 31744063, 31744065, 31744067, 31744069, 31744071, 31744073, 31744075, 31744077, 31744079, 31744081, + 31744083, 31744085, 31744087, 31744089, 31744091, 31744093, 31744095, 31744097, 31744099, 31744101, 31744103, 31744105, 31744107, 31744109, 31744111, + 31744113, 31744115, 31744117, 31744119, 31744121, 31744123, 31744125, 31744127, 31768449, 31768451, 31768453, 31768455, 31768457, 31768459, 31768461, + 31768463, 31768465, 31768467, 31768469, 31768471, 31768473, 31768475, 31768477, 31768479, 31768481, 31768483, 31768485, 31768487, 31768489, 31768491, + 31768493, 31768495, 31768497, 31768499, 31768501, 31768503, 31768505, 31768507, 31768509, 31768511, 31768513, 31768515, 31768517, 31768519, 31768521, + 31768523, 31768525, 31768527, 31768529, 31768531, 31768533, 31768535, 31768537, 31768539, 31768541, 31768543, 31768545, 31768547, 31768549, 31768551, + 31768553, 31768555, 31768557, 31768559, 31768561, 31768563, 31768565, 31768567, 31768569, 31768571, 6205, 61, 0, 60, 6204, + 31760391, 31760393, 31760395, 31760397, 31760399, 31760401, 31760403, 31760405, 31760407, 31760409, 31760411, 31760413, 31760415, 31760417, 31760419, + 31760421, 31760423, 31760425, 31760427, 31760429, 31760431, 31760433, 31760435, 31760437, 31760439, 31760441, 31760443, 31760445, 31760447, 31760449, + 31760451, 31760453, 31760455, 31760457, 31760459, 31760461, 31760463, 31760465, 31760467, 31760469, 31760471, 31760473, 31760475, 31760477, 31760479, + 31760481, 31760483, 31760485, 31760487, 31760489, 31760491, 31760493, 31760495, 31760497, 31760499, 31760501, 31760503, 31760505, 31760507, 31760509, + 31760511, 31784833, 31784835, 31784837, 31784839, 31784841, 31784843, 31784845, 31784847, 31784849, 31784851, 31784853, 31784855, 31784857, 31784859, + 31784861, 31784863, 31784865, 31784867, 31784869, 31784871, 31784873, 31784875, 31784877, 31784879, 31784881, 31784883, 31784885, 31784887, 31784889, + 31784891, 31784893, 31784895, 31784897, 31784899, 31784901, 31784903, 31784905, 31784907, 31784909, 31784911, 31784913, 31784915, 31784917, 31784919, + 31784921, 31784923, 31784925, 31784927, 31784929, 31784931, 31784933, 31784935, 31784937, 31784939, 31784941, 31784943, 31784945, 31784947, 31784949, + 31784951, 31784953, 31784955, 6203, 59, 0, 58, 6202, 31776775, 31776777, 31776779, 31776781, 31776783, 31776785, 31776787, + 31776789, 31776791, 31776793, 31776795, 31776797, 31776799, 31776801, 31776803, 31776805, 31776807, 31776809, 31776811, 31776813, 31776815, 31776817, + 31776819, 31776821, 31776823, 31776825, 31776827, 31776829, 31776831, 31776833, 31776835, 31776837, 31776839, 31776841, 31776843, 31776845, 31776847, + 31776849, 31776851, 31776853, 31776855, 31776857, 31776859, 31776861, 31776863, 31776865, 31776867, 31776869, 31776871, 31776873, 31776875, 31776877, + 31776879, 31776881, 31776883, 31776885, 31776887, 31776889, 31776891, 31776893, 31776895, 31801217, 31801219, 31801221, 31801223, 31801225, 31801227, + 31801229, 31801231, 31801233, 31801235, 31801237, 31801239, 31801241, 31801243, 31801245, 31801247, 31801249, 31801251, 31801253, 31801255, 31801257, + 31801259, 31801261, 31801263, 31801265, 31801267, 31801269, 31801271, 31801273, 31801275, 31801277, 31801279, 31801281, 31801283, 31801285, 31801287, + 31801289, 31801291, 31801293, 31801295, 31801297, 31801299, 31801301, 31801303, 31801305, 31801307, 31801309, 31801311, 31801313, 31801315, 31801317, + 31801319, 31801321, 31801323, 31801325, 31801327, 31801329, 31801331, 31801333, 31801335, 31801337, 31801339, 6201, 57, 0, 56, + 6200, 31793159, 31793161, 31793163, 31793165, 31793167, 31793169, 31793171, 31793173, 31793175, 31793177, 31793179, 31793181, 31793183, 31793185, + 31793187, 31793189, 31793191, 31793193, 31793195, 31793197, 31793199, 31793201, 31793203, 31793205, 31793207, 31793209, 31793211, 31793213, 31793215, + 31793217, 31793219, 31793221, 31793223, 31793225, 31793227, 31793229, 31793231, 31793233, 31793235, 31793237, 31793239, 31793241, 31793243, 31793245, + 31793247, 31793249, 31793251, 31793253, 31793255, 31793257, 31793259, 31793261, 31793263, 31793265, 31793267, 31793269, 31793271, 31793273, 31793275, + 31793277, 31793279, 31817601, 31817603, 31817605, 31817607, 31817609, 31817611, 31817613, 31817615, 31817617, 31817619, 31817621, 31817623, 31817625, + 31817627, 31817629, 31817631, 31817633, 31817635, 31817637, 31817639, 31817641, 31817643, 31817645, 31817647, 31817649, 31817651, 31817653, 31817655, + 31817657, 31817659, 31817661, 31817663, 31817665, 31817667, 31817669, 31817671, 31817673, 31817675, 31817677, 31817679, 31817681, 31817683, 31817685, + 31817687, 31817689, 31817691, 31817693, 31817695, 31817697, 31817699, 31817701, 31817703, 31817705, 31817707, 31817709, 31817711, 31817713, 31817715, + 31817717, 31817719, 31817721, 31817723, 6199, 55, 0, 54, 6198, 31809543, 31809545, 31809547, 31809549, 31809551, 31809553, + 31809555, 31809557, 31809559, 31809561, 31809563, 31809565, 31809567, 31809569, 31809571, 31809573, 31809575, 31809577, 31809579, 31809581, 31809583, + 31809585, 31809587, 31809589, 31809591, 31809593, 31809595, 31809597, 31809599, 31809601, 31809603, 31809605, 31809607, 31809609, 31809611, 31809613, + 31809615, 31809617, 31809619, 31809621, 31809623, 31809625, 31809627, 31809629, 31809631, 31809633, 31809635, 31809637, 31809639, 31809641, 31809643, + 31809645, 31809647, 31809649, 31809651, 31809653, 31809655, 31809657, 31809659, 31809661, 31809663, 31833985, 31833987, 31833989, 31833991, 31833993, + 31833995, 31833997, 31833999, 31834001, 31834003, 31834005, 31834007, 31834009, 31834011, 31834013, 31834015, 31834017, 31834019, 31834021, 31834023, + 31834025, 31834027, 31834029, 31834031, 31834033, 31834035, 31834037, 31834039, 31834041, 31834043, 31834045, 31834047, 31834049, 31834051, 31834053, + 31834055, 31834057, 31834059, 31834061, 31834063, 31834065, 31834067, 31834069, 31834071, 31834073, 31834075, 31834077, 31834079, 31834081, 31834083, + 31834085, 31834087, 31834089, 31834091, 31834093, 31834095, 31834097, 31834099, 31834101, 31834103, 31834105, 31834107, 6197, 53, 0, + 52, 6196, 31825927, 31825929, 31825931, 31825933, 31825935, 31825937, 31825939, 31825941, 31825943, 31825945, 31825947, 31825949, 31825951, + 31825953, 31825955, 31825957, 31825959, 31825961, 31825963, 31825965, 31825967, 31825969, 31825971, 31825973, 31825975, 31825977, 31825979, 31825981, + 31825983, 31825985, 31825987, 31825989, 31825991, 31825993, 31825995, 31825997, 31825999, 31826001, 31826003, 31826005, 31826007, 31826009, 31826011, + 31826013, 31826015, 31826017, 31826019, 31826021, 31826023, 31826025, 31826027, 31826029, 31826031, 31826033, 31826035, 31826037, 31826039, 31826041, + 31826043, 31826045, 31826047, 31850369, 31850371, 31850373, 31850375, 31850377, 31850379, 31850381, 31850383, 31850385, 31850387, 31850389, 31850391, + 31850393, 31850395, 31850397, 31850399, 31850401, 31850403, 31850405, 31850407, 31850409, 31850411, 31850413, 31850415, 31850417, 31850419, 31850421, + 31850423, 31850425, 31850427, 31850429, 31850431, 31850433, 31850435, 31850437, 31850439, 31850441, 31850443, 31850445, 31850447, 31850449, 31850451, + 31850453, 31850455, 31850457, 31850459, 31850461, 31850463, 31850465, 31850467, 31850469, 31850471, 31850473, 31850475, 31850477, 31850479, 31850481, + 31850483, 31850485, 31850487, 31850489, 31850491, 24645, 69, 0, 68, 24644, 31842311, 31842313, 31842315, 31842317, 31842319, + 31842321, 31842323, 31842325, 31842327, 31842329, 31842331, 31842333, 31842335, 31842337, 31842339, 31842341, 31842343, 31842345, 31842347, 31842349, + 31842351, 31842353, 31842355, 31842357, 31842359, 31842361, 31842363, 31842365, 31842367, 31842369, 31842371, 31842373, 31842375, 31842377, 31842379, + 31842381, 31842383, 31842385, 31842387, 31842389, 31842391, 31842393, 31842395, 31842397, 31842399, 31842401, 31842403, 31842405, 31842407, 31842409, + 31842411, 31842413, 31842415, 31842417, 31842419, 31842421, 31842423, 31842425, 31842427, 31842429, 31842431, 31866753, 31866755, 31866757, 31866759, + 31866761, 31866763, 31866765, 31866767, 31866769, 31866771, 31866773, 31866775, 31866777, 31866779, 31866781, 31866783, 31866785, 31866787, 31866789, + 31866791, 31866793, 31866795, 31866797, 31866799, 31866801, 31866803, 31866805, 31866807, 31866809, 31866811, 31866813, 31866815, 31866817, 31866819, + 31866821, 31866823, 31866825, 31866827, 31866829, 31866831, 31866833, 31866835, 31866837, 31866839, 31866841, 31866843, 31866845, 31866847, 31866849, + 31866851, 31866853, 31866855, 31866857, 31866859, 31866861, 31866863, 31866865, 31866867, 31866869, 31866871, 31866873, 31866875, 24647, 71, + 0, 70, 24646, 31858695, 31858697, 31858699, 31858701, 31858703, 31858705, 31858707, 31858709, 31858711, 31858713, 31858715, 31858717, + 31858719, 31858721, 31858723, 31858725, 31858727, 31858729, 31858731, 31858733, 31858735, 31858737, 31858739, 31858741, 31858743, 31858745, 31858747, + 31858749, 31858751, 31858753, 31858755, 31858757, 31858759, 31858761, 31858763, 31858765, 31858767, 31858769, 31858771, 31858773, 31858775, 31858777, + 31858779, 31858781, 31858783, 31858785, 31858787, 31858789, 31858791, 31858793, 31858795, 31858797, 31858799, 31858801, 31858803, 31858805, 31858807, + 31858809, 31858811, 31858813, 31858815, 31883137, 31883139, 31883141, 31883143, 31883145, 31883147, 31883149, 31883151, 31883153, 31883155, 31883157, + 31883159, 31883161, 31883163, 31883165, 31883167, 31883169, 31883171, 31883173, 31883175, 31883177, 31883179, 31883181, 31883183, 31883185, 31883187, + 31883189, 31883191, 31883193, 31883195, 31883197, 31883199, 31883201, 31883203, 31883205, 31883207, 31883209, 31883211, 31883213, 31883215, 31883217, + 31883219, 31883221, 31883223, 31883225, 31883227, 31883229, 31883231, 31883233, 31883235, 31883237, 31883239, 31883241, 31883243, 31883245, 31883247, + 31883249, 31883251, 31883253, 31883255, 31883257, 31883259, 49325, 173, 0, 172, 49324, 31875079, 31875081, 31875083, 31875085, + 31875087, 31875089, 31875091, 31875093, 31875095, 31875097, 31875099, 31875101, 31875103, 31875105, 31875107, 31875109, 31875111, 31875113, 31875115, + 31875117, 31875119, 31875121, 31875123, 31875125, 31875127, 31875129, 31875131, 31875133, 31875135, 31875137, 31875139, 31875141, 31875143, 31875145, + 31875147, 31875149, 31875151, 31875153, 31875155, 31875157, 31875159, 31875161, 31875163, 31875165, 31875167, 31875169, 31875171, 31875173, 31875175, + 31875177, 31875179, 31875181, 31875183, 31875185, 31875187, 31875189, 31875191, 31875193, 31875195, 31875197, 31875199, 31899521, 31899523, 31899525, + 31899527, 31899529, 31899531, 31899533, 31899535, 31899537, 31899539, 31899541, 31899543, 31899545, 31899547, 31899549, 31899551, 31899553, 31899555, + 31899557, 31899559, 31899561, 31899563, 31899565, 31899567, 31899569, 31899571, 31899573, 31899575, 31899577, 31899579, 31899581, 31899583, 31899585, + 31899587, 31899589, 31899591, 31899593, 31899595, 31899597, 31899599, 31899601, 31899603, 31899605, 31899607, 31899609, 31899611, 31899613, 31899615, + 31899617, 31899619, 31899621, 31899623, 31899625, 31899627, 31899629, 31899631, 31899633, 31899635, 31899637, 31899639, 31899641, 31899643, 49327, + 175, 0, 174, 49326, 31891463, 31891465, 31891467, 31891469, 31891471, 31891473, 31891475, 31891477, 31891479, 31891481, 31891483, + 31891485, 31891487, 31891489, 31891491, 31891493, 31891495, 31891497, 31891499, 31891501, 31891503, 31891505, 31891507, 31891509, 31891511, 31891513, + 31891515, 31891517, 31891519, 31891521, 31891523, 31891525, 31891527, 31891529, 31891531, 31891533, 31891535, 31891537, 31891539, 31891541, 31891543, + 31891545, 31891547, 31891549, 31891551, 31891553, 31891555, 31891557, 31891559, 31891561, 31891563, 31891565, 31891567, 31891569, 31891571, 31891573, + 31891575, 31891577, 31891579, 31891581, 31891583, 31915905, 31915907, 31915909, 31915911, 31915913, 31915915, 31915917, 31915919, 31915921, 31915923, + 31915925, 31915927, 31915929, 31915931, 31915933, 31915935, 31915937, 31915939, 31915941, 31915943, 31915945, 31915947, 31915949, 31915951, 31915953, + 31915955, 31915957, 31915959, 31915961, 31915963, 31915965, 31915967, 31915969, 31915971, 31915973, 31915975, 31915977, 31915979, 31915981, 31915983, + 31915985, 31915987, 31915989, 31915991, 31915993, 31915995, 31915997, 31915999, 31916001, 31916003, 31916005, 31916007, 31916009, 31916011, 31916013, + 31916015, 31916017, 31916019, 31916021, 31916023, 31916025, 31916027, 31916029, 117, 0, 116, 31907845, 31907847, 31907849, 31907851, + 31907853, 31907855, 31907857, 31907859, 31907861, 31907863, 31907865, 31907867, 31907869, 31907871, 31907873, 31907875, 31907877, 31907879, 31907881, + 31907883, 31907885, 31907887, 31907889, 31907891, 31907893, 31907895, 31907897, 31907899, 31907901, 31907903, 31907905, 31907907, 31907909, 31907911, + 31907913, 31907915, 31907917, 31907919, 31907921, 31907923, 31907925, 31907927, 31907929, 31907931, 31907933, 31907935, 31907937, 31907939, 31907941, + 31907943, 31907945, 31907947, 31907949, 31907951, 31907953, 31907955, 31907957, 31907959, 31907961, 31907963, 31907965, 31907967, 31932289, 31932291, + 31932293, 31932295, 31932297, 31932299, 31932301, 31932303, 31932305, 31932307, 31932309, 31932311, 31932313, 31932315, 31932317, 31932319, 31932321, + 31932323, 31932325, 31932327, 31932329, 31932331, 31932333, 31932335, 31932337, 31932339, 31932341, 31932343, 31932345, 31932347, 31932349, 31932351, + 31932353, 31932355, 31932357, 31932359, 31932361, 31932363, 31932365, 31932367, 31932369, 31932371, 31932373, 31932375, 31932377, 31932379, 31932381, + 31932383, 31932385, 31932387, 31932389, 31932391, 31932393, 31932395, 31932397, 31932399, 31932401, 31932403, 31932405, 31932407, 31932409, 31932411, + 31932413, 237, 0, 236, 31924229, 31924231, 31924233, 31924235, 31924237, 31924239, 31924241, 31924243, 31924245, 31924247, 31924249, + 31924251, 31924253, 31924255, 31924257, 31924259, 31924261, 31924263, 31924265, 31924267, 31924269, 31924271, 31924273, 31924275, 31924277, 31924279, + 31924281, 31924283, 31924285, 31924287, 31924289, 31924291, 31924293, 31924295, 31924297, 31924299, 31924301, 31924303, 31924305, 31924307, 31924309, + 31924311, 31924313, 31924315, 31924317, 31924319, 31924321, 31924323, 31924325, 31924327, 31924329, 31924331, 31924333, 31924335, 31924337, 31924339, + 31924341, 31924343, 31924345, 31924347, 31924349, 31924351, 31948673, 31948675, 31948677, 31948679, 31948681, 31948683, 31948685, 31948687, 31948689, + 31948691, 31948693, 31948695, 31948697, 31948699, 31948701, 31948703, 31948705, 31948707, 31948709, 31948711, 31948713, 31948715, 31948717, 31948719, + 31948721, 31948723, 31948725, 31948727, 31948729, 31948731, 31948733, 31948735, 31948737, 31948739, 31948741, 31948743, 31948745, 31948747, 31948749, + 31948751, 31948753, 31948755, 31948757, 31948759, 31948761, 31948763, 31948765, 31948767, 31948769, 31948771, 31948773, 31948775, 31948777, 31948779, + 31948781, 31948783, 31948785, 31948787, 31948789, 31948791, 31948793, 31948795, 31948797, 477, 0, 476, 31940613, 31940615, 31940617, + 31940619, 31940621, 31940623, 31940625, 31940627, 31940629, 31940631, 31940633, 31940635, 31940637, 31940639, 31940641, 31940643, 31940645, 31940647, + 31940649, 31940651, 31940653, 31940655, 31940657, 31940659, 31940661, 31940663, 31940665, 31940667, 31940669, 31940671, 31940673, 31940675, 31940677, + 31940679, 31940681, 31940683, 31940685, 31940687, 31940689, 31940691, 31940693, 31940695, 31940697, 31940699, 31940701, 31940703, 31940705, 31940707, + 31940709, 31940711, 31940713, 31940715, 31940717, 31940719, 31940721, 31940723, 31940725, 31940727, 31940729, 31940731, 31940733, 31940735, 31965057, + 31965059, 31965061, 31965063, 31965065, 31965067, 31965069, 31965071, 31965073, 31965075, 31965077, 31965079, 31965081, 31965083, 31965085, 31965087, + 31965089, 31965091, 31965093, 31965095, 31965097, 31965099, 31965101, 31965103, 31965105, 31965107, 31965109, 31965111, 31965113, 31965115, 31965117, + 31965119, 31965121, 31965123, 31965125, 31965127, 31965129, 31965131, 31965133, 31965135, 31965137, 31965139, 31965141, 31965143, 31965145, 31965147, + 31965149, 31965151, 31965153, 31965155, 31965157, 31965159, 31965161, 31965163, 31965165, 31965167, 31965169, 31965171, 31965173, 31965175, 31965177, + 31965179, 31965181, 923, 0, 922, 31956997, 31956999, 31957001, 31957003, 31957005, 31957007, 31957009, 31957011, 31957013, 31957015, + 31957017, 31957019, 31957021, 31957023, 31957025, 31957027, 31957029, 31957031, 31957033, 31957035, 31957037, 31957039, 31957041, 31957043, 31957045, + 31957047, 31957049, 31957051, 31957053, 31957055, 31957057, 31957059, 31957061, 31957063, 31957065, 31957067, 31957069, 31957071, 31957073, 31957075, + 31957077, 31957079, 31957081, 31957083, 31957085, 31957087, 31957089, 31957091, 31957093, 31957095, 31957097, 31957099, 31957101, 31957103, 31957105, + 31957107, 31957109, 31957111, 31957113, 31957115, 31957117, 31957119, 31981441, 31981443, 31981445, 31981447, 31981449, 31981451, 31981453, 31981455, + 31981457, 31981459, 31981461, 31981463, 31981465, 31981467, 31981469, 31981471, 31981473, 31981475, 31981477, 31981479, 31981481, 31981483, 31981485, + 31981487, 31981489, 31981491, 31981493, 31981495, 31981497, 31981499, 31981501, 31981503, 31981505, 31981507, 31981509, 31981511, 31981513, 31981515, + 31981517, 31981519, 31981521, 31981523, 31981525, 31981527, 31981529, 31981531, 31981533, 31981535, 31981537, 31981539, 31981541, 31981543, 31981545, + 31981547, 31981549, 31981551, 31981553, 31981555, 31981557, 31981559, 31981561, 31981563, 31981565, 921, 0, 920, 31973381, 31973383, + 31973385, 31973387, 31973389, 31973391, 31973393, 31973395, 31973397, 31973399, 31973401, 31973403, 31973405, 31973407, 31973409, 31973411, 31973413, + 31973415, 31973417, 31973419, 31973421, 31973423, 31973425, 31973427, 31973429, 31973431, 31973433, 31973435, 31973437, 31973439, 31973441, 31973443, + 31973445, 31973447, 31973449, 31973451, 31973453, 31973455, 31973457, 31973459, 31973461, 31973463, 31973465, 31973467, 31973469, 31973471, 31973473, + 31973475, 31973477, 31973479, 31973481, 31973483, 31973485, 31973487, 31973489, 31973491, 31973493, 31973495, 31973497, 31973499, 31973501, 31973503, + 31997825, 31997827, 31997829, 31997831, 31997833, 31997835, 31997837, 31997839, 31997841, 31997843, 31997845, 31997847, 31997849, 31997851, 31997853, + 31997855, 31997857, 31997859, 31997861, 31997863, 31997865, 31997867, 31997869, 31997871, 31997873, 31997875, 31997877, 31997879, 31997881, 31997883, + 31997885, 31997887, 31997889, 31997891, 31997893, 31997895, 31997897, 31997899, 31997901, 31997903, 31997905, 31997907, 31997909, 31997911, 31997913, + 31997915, 31997917, 31997919, 31997921, 31997923, 31997925, 31997927, 31997929, 31997931, 31997933, 31997935, 31997937, 31997939, 31997941, 31997943, + 31997945, 31997947, 31997949, 919, 0, 918, 31989765, 31989767, 31989769, 31989771, 31989773, 31989775, 31989777, 31989779, 31989781, + 31989783, 31989785, 31989787, 31989789, 31989791, 31989793, 31989795, 31989797, 31989799, 31989801, 31989803, 31989805, 31989807, 31989809, 31989811, + 31989813, 31989815, 31989817, 31989819, 31989821, 31989823, 31989825, 31989827, 31989829, 31989831, 31989833, 31989835, 31989837, 31989839, 31989841, + 31989843, 31989845, 31989847, 31989849, 31989851, 31989853, 31989855, 31989857, 31989859, 31989861, 31989863, 31989865, 31989867, 31989869, 31989871, + 31989873, 31989875, 31989877, 31989879, 31989881, 31989883, 31989885, 31989887, 32014209, 32014211, 32014213, 32014215, 32014217, 32014219, 32014221, + 32014223, 32014225, 32014227, 32014229, 32014231, 32014233, 32014235, 32014237, 32014239, 32014241, 32014243, 32014245, 32014247, 32014249, 32014251, + 32014253, 32014255, 32014257, 32014259, 32014261, 32014263, 32014265, 32014267, 32014269, 32014271, 32014273, 32014275, 32014277, 32014279, 32014281, + 32014283, 32014285, 32014287, 32014289, 32014291, 32014293, 32014295, 32014297, 32014299, 32014301, 32014303, 32014305, 32014307, 32014309, 32014311, + 32014313, 32014315, 32014317, 32014319, 32014321, 32014323, 32014325, 32014327, 32014329, 32014331, 32014333, 1831, 0, 1830, 32006149, + 32006151, 32006153, 32006155, 32006157, 32006159, 32006161, 32006163, 32006165, 32006167, 32006169, 32006171, 32006173, 32006175, 32006177, 32006179, + 32006181, 32006183, 32006185, 32006187, 32006189, 32006191, 32006193, 32006195, 32006197, 32006199, 32006201, 32006203, 32006205, 32006207, 32006209, + 32006211, 32006213, 32006215, 32006217, 32006219, 32006221, 32006223, 32006225, 32006227, 32006229, 32006231, 32006233, 32006235, 32006237, 32006239, + 32006241, 32006243, 32006245, 32006247, 32006249, 32006251, 32006253, 32006255, 32006257, 32006259, 32006261, 32006263, 32006265, 32006267, 32006269, + 32006271, 32030593, 32030595, 32030597, 32030599, 32030601, 32030603, 32030605, 32030607, 32030609, 32030611, 32030613, 32030615, 32030617, 32030619, + 32030621, 32030623, 32030625, 32030627, 32030629, 32030631, 32030633, 32030635, 32030637, 32030639, 32030641, 32030643, 32030645, 32030647, 32030649, + 32030651, 32030653, 32030655, 32030657, 32030659, 32030661, 32030663, 32030665, 32030667, 32030669, 32030671, 32030673, 32030675, 32030677, 32030679, + 32030681, 32030683, 32030685, 32030687, 32030689, 32030691, 32030693, 32030695, 32030697, 32030699, 32030701, 32030703, 32030705, 32030707, 32030709, + 32030711, 32030713, 32030715, 32030717, 1829, 0, 1828, 32022533, 32022535, 32022537, 32022539, 32022541, 32022543, 32022545, 32022547, + 32022549, 32022551, 32022553, 32022555, 32022557, 32022559, 32022561, 32022563, 32022565, 32022567, 32022569, 32022571, 32022573, 32022575, 32022577, + 32022579, 32022581, 32022583, 32022585, 32022587, 32022589, 32022591, 32022593, 32022595, 32022597, 32022599, 32022601, 32022603, 32022605, 32022607, + 32022609, 32022611, 32022613, 32022615, 32022617, 32022619, 32022621, 32022623, 32022625, 32022627, 32022629, 32022631, 32022633, 32022635, 32022637, + 32022639, 32022641, 32022643, 32022645, 32022647, 32022649, 32022651, 32022653, 32022655, 32046977, 32046979, 32046981, 32046983, 32046985, 32046987, + 32046989, 32046991, 32046993, 32046995, 32046997, 32046999, 32047001, 32047003, 32047005, 32047007, 32047009, 32047011, 32047013, 32047015, 32047017, + 32047019, 32047021, 32047023, 32047025, 32047027, 32047029, 32047031, 32047033, 32047035, 32047037, 32047039, 32047041, 32047043, 32047045, 32047047, + 32047049, 32047051, 32047053, 32047055, 32047057, 32047059, 32047061, 32047063, 32047065, 32047067, 32047069, 32047071, 32047073, 32047075, 32047077, + 32047079, 32047081, 32047083, 32047085, 32047087, 32047089, 32047091, 32047093, 32047095, 32047097, 32047099, 32047101, 1827, 0, 1826, + 32038917, 32038919, 32038921, 32038923, 32038925, 32038927, 32038929, 32038931, 32038933, 32038935, 32038937, 32038939, 32038941, 32038943, 32038945, + 32038947, 32038949, 32038951, 32038953, 32038955, 32038957, 32038959, 32038961, 32038963, 32038965, 32038967, 32038969, 32038971, 32038973, 32038975, + 32038977, 32038979, 32038981, 32038983, 32038985, 32038987, 32038989, 32038991, 32038993, 32038995, 32038997, 32038999, 32039001, 32039003, 32039005, + 32039007, 32039009, 32039011, 32039013, 32039015, 32039017, 32039019, 32039021, 32039023, 32039025, 32039027, 32039029, 32039031, 32039033, 32039035, + 32039037, 32039039, 32063361, 32063363, 32063365, 32063367, 32063369, 32063371, 32063373, 32063375, 32063377, 32063379, 32063381, 32063383, 32063385, + 32063387, 32063389, 32063391, 32063393, 32063395, 32063397, 32063399, 32063401, 32063403, 32063405, 32063407, 32063409, 32063411, 32063413, 32063415, + 32063417, 32063419, 32063421, 32063423, 32063425, 32063427, 32063429, 32063431, 32063433, 32063435, 32063437, 32063439, 32063441, 32063443, 32063445, + 32063447, 32063449, 32063451, 32063453, 32063455, 32063457, 32063459, 32063461, 32063463, 32063465, 32063467, 32063469, 32063471, 32063473, 32063475, + 32063477, 32063479, 32063481, 32063483, 32063485, 1825, 0, 1824, 32055301, 32055303, 32055305, 32055307, 32055309, 32055311, 32055313, + 32055315, 32055317, 32055319, 32055321, 32055323, 32055325, 32055327, 32055329, 32055331, 32055333, 32055335, 32055337, 32055339, 32055341, 32055343, + 32055345, 32055347, 32055349, 32055351, 32055353, 32055355, 32055357, 32055359, 32055361, 32055363, 32055365, 32055367, 32055369, 32055371, 32055373, + 32055375, 32055377, 32055379, 32055381, 32055383, 32055385, 32055387, 32055389, 32055391, 32055393, 32055395, 32055397, 32055399, 32055401, 32055403, + 32055405, 32055407, 32055409, 32055411, 32055413, 32055415, 32055417, 32055419, 32055421, 32055423, 32079745, 32079747, 32079749, 32079751, 32079753, + 32079755, 32079757, 32079759, 32079761, 32079763, 32079765, 32079767, 32079769, 32079771, 32079773, 32079775, 32079777, 32079779, 32079781, 32079783, + 32079785, 32079787, 32079789, 32079791, 32079793, 32079795, 32079797, 32079799, 32079801, 32079803, 32079805, 32079807, 32079809, 32079811, 32079813, + 32079815, 32079817, 32079819, 32079821, 32079823, 32079825, 32079827, 32079829, 32079831, 32079833, 32079835, 32079837, 32079839, 32079841, 32079843, + 32079845, 32079847, 32079849, 32079851, 32079853, 32079855, 32079857, 32079859, 32079861, 32079863, 32079865, 32079867, 32079869, 3629, 0, + 3628, 32071685, 32071687, 32071689, 32071691, 32071693, 32071695, 32071697, 32071699, 32071701, 32071703, 32071705, 32071707, 32071709, 32071711, + 32071713, 32071715, 32071717, 32071719, 32071721, 32071723, 32071725, 32071727, 32071729, 32071731, 32071733, 32071735, 32071737, 32071739, 32071741, + 32071743, 32071745, 32071747, 32071749, 32071751, 32071753, 32071755, 32071757, 32071759, 32071761, 32071763, 32071765, 32071767, 32071769, 32071771, + 32071773, 32071775, 32071777, 32071779, 32071781, 32071783, 32071785, 32071787, 32071789, 32071791, 32071793, 32071795, 32071797, 32071799, 32071801, + 32071803, 32071805, 32071807, 32096129, 32096131, 32096133, 32096135, 32096137, 32096139, 32096141, 32096143, 32096145, 32096147, 32096149, 32096151, + 32096153, 32096155, 32096157, 32096159, 32096161, 32096163, 32096165, 32096167, 32096169, 32096171, 32096173, 32096175, 32096177, 32096179, 32096181, + 32096183, 32096185, 32096187, 32096189, 32096191, 32096193, 32096195, 32096197, 32096199, 32096201, 32096203, 32096205, 32096207, 32096209, 32096211, + 32096213, 32096215, 32096217, 32096219, 32096221, 32096223, 32096225, 32096227, 32096229, 32096231, 32096233, 32096235, 32096237, 32096239, 32096241, + 32096243, 32096245, 32096247, 32096249, 32096251, 32096253, 3627, 0, 3626, 32088069, 32088071, 32088073, 32088075, 32088077, 32088079, + 32088081, 32088083, 32088085, 32088087, 32088089, 32088091, 32088093, 32088095, 32088097, 32088099, 32088101, 32088103, 32088105, 32088107, 32088109, + 32088111, 32088113, 32088115, 32088117, 32088119, 32088121, 32088123, 32088125, 32088127, 32088129, 32088131, 32088133, 32088135, 32088137, 32088139, + 32088141, 32088143, 32088145, 32088147, 32088149, 32088151, 32088153, 32088155, 32088157, 32088159, 32088161, 32088163, 32088165, 32088167, 32088169, + 32088171, 32088173, 32088175, 32088177, 32088179, 32088181, 32088183, 32088185, 32088187, 32088189, 32088191, 32112513, 32112515, 32112517, 32112519, + 32112521, 32112523, 32112525, 32112527, 32112529, 32112531, 32112533, 32112535, 32112537, 32112539, 32112541, 32112543, 32112545, 32112547, 32112549, + 32112551, 32112553, 32112555, 32112557, 32112559, 32112561, 32112563, 32112565, 32112567, 32112569, 32112571, 32112573, 32112575, 32112577, 32112579, + 32112581, 32112583, 32112585, 32112587, 32112589, 32112591, 32112593, 32112595, 32112597, 32112599, 32112601, 32112603, 32112605, 32112607, 32112609, + 32112611, 32112613, 32112615, 32112617, 32112619, 32112621, 32112623, 32112625, 32112627, 32112629, 32112631, 32112633, 32112635, 32112637, 3625, + 0, 3624, 32104453, 32104455, 32104457, 32104459, 32104461, 32104463, 32104465, 32104467, 32104469, 32104471, 32104473, 32104475, 32104477, + 32104479, 32104481, 32104483, 32104485, 32104487, 32104489, 32104491, 32104493, 32104495, 32104497, 32104499, 32104501, 32104503, 32104505, 32104507, + 32104509, 32104511, 32104513, 32104515, 32104517, 32104519, 32104521, 32104523, 32104525, 32104527, 32104529, 32104531, 32104533, 32104535, 32104537, + 32104539, 32104541, 32104543, 32104545, 32104547, 32104549, 32104551, 32104553, 32104555, 32104557, 32104559, 32104561, 32104563, 32104565, 32104567, + 32104569, 32104571, 32104573, 32104575, 32128897, 32128899, 32128901, 32128903, 32128905, 32128907, 32128909, 32128911, 32128913, 32128915, 32128917, + 32128919, 32128921, 32128923, 32128925, 32128927, 32128929, 32128931, 32128933, 32128935, 32128937, 32128939, 32128941, 32128943, 32128945, 32128947, + 32128949, 32128951, 32128953, 32128955, 32128957, 32128959, 32128961, 32128963, 32128965, 32128967, 32128969, 32128971, 32128973, 32128975, 32128977, + 32128979, 32128981, 32128983, 32128985, 32128987, 32128989, 32128991, 32128993, 32128995, 32128997, 32128999, 32129001, 32129003, 32129005, 32129007, + 32129009, 32129011, 32129013, 32129015, 32129017, 32129019, 32129021, 7225, 0, 7224, 32120837, 32120839, 32120841, 32120843, 32120845, + 32120847, 32120849, 32120851, 32120853, 32120855, 32120857, 32120859, 32120861, 32120863, 32120865, 32120867, 32120869, 32120871, 32120873, 32120875, + 32120877, 32120879, 32120881, 32120883, 32120885, 32120887, 32120889, 32120891, 32120893, 32120895, 32120897, 32120899, 32120901, 32120903, 32120905, + 32120907, 32120909, 32120911, 32120913, 32120915, 32120917, 32120919, 32120921, 32120923, 32120925, 32120927, 32120929, 32120931, 32120933, 32120935, + 32120937, 32120939, 32120941, 32120943, 32120945, 32120947, 32120949, 32120951, 32120953, 32120955, 32120957, 32120959, 32145281, 32145283, 32145285, + 32145287, 32145289, 32145291, 32145293, 32145295, 32145297, 32145299, 32145301, 32145303, 32145305, 32145307, 32145309, 32145311, 32145313, 32145315, + 32145317, 32145319, 32145321, 32145323, 32145325, 32145327, 32145329, 32145331, 32145333, 32145335, 32145337, 32145339, 32145341, 32145343, 32145345, + 32145347, 32145349, 32145351, 32145353, 32145355, 32145357, 32145359, 32145361, 32145363, 32145365, 32145367, 32145369, 32145371, 32145373, 32145375, + 32145377, 32145379, 32145381, 32145383, 32145385, 32145387, 32145389, 32145391, 32145393, 32145395, 32145397, 32145399, 32145401, 32145403, 32145405, + 7223, 0, 7222, 32137221, 32137223, 32137225, 32137227, 32137229, 32137231, 32137233, 32137235, 32137237, 32137239, 32137241, 32137243, + 32137245, 32137247, 32137249, 32137251, 32137253, 32137255, 32137257, 32137259, 32137261, 32137263, 32137265, 32137267, 32137269, 32137271, 32137273, + 32137275, 32137277, 32137279, 32137281, 32137283, 32137285, 32137287, 32137289, 32137291, 32137293, 32137295, 32137297, 32137299, 32137301, 32137303, + 32137305, 32137307, 32137309, 32137311, 32137313, 32137315, 32137317, 32137319, 32137321, 32137323, 32137325, 32137327, 32137329, 32137331, 32137333, + 32137335, 32137337, 32137339, 32137341, 32137343, 32161665, 32161667, 32161669, 32161671, 32161673, 32161675, 32161677, 32161679, 32161681, 32161683, + 32161685, 32161687, 32161689, 32161691, 32161693, 32161695, 32161697, 32161699, 32161701, 32161703, 32161705, 32161707, 32161709, 32161711, 32161713, + 32161715, 32161717, 32161719, 32161721, 32161723, 32161725, 32161727, 32161729, 32161731, 32161733, 32161735, 32161737, 32161739, 32161741, 32161743, + 32161745, 32161747, 32161749, 32161751, 32161753, 32161755, 32161757, 32161759, 32161761, 32161763, 32161765, 32161767, 32161769, 32161771, 32161773, + 32161775, 32161777, 32161779, 32161781, 32161783, 32161785, 32161787, 32161789, 14403, 0, 14402, 32153605, 32153607, 32153609, 32153611, + 32153613, 32153615, 32153617, 32153619, 32153621, 32153623, 32153625, 32153627, 32153629, 32153631, 32153633, 32153635, 32153637, 32153639, 32153641, + 32153643, 32153645, 32153647, 32153649, 32153651, 32153653, 32153655, 32153657, 32153659, 32153661, 32153663, 32153665, 32153667, 32153669, 32153671, + 32153673, 32153675, 32153677, 32153679, 32153681, 32153683, 32153685, 32153687, 32153689, 32153691, 32153693, 32153695, 32153697, 32153699, 32153701, + 32153703, 32153705, 32153707, 32153709, 32153711, 32153713, 32153715, 32153717, 32153719, 32153721, 32153723, 32153725, 32153727, 32178049, 32178051, + 32178053, 32178055, 32178057, 32178059, 32178061, 32178063, 32178065, 32178067, 32178069, 32178071, 32178073, 32178075, 32178077, 32178079, 32178081, + 32178083, 32178085, 32178087, 32178089, 32178091, 32178093, 32178095, 32178097, 32178099, 32178101, 32178103, 32178105, 32178107, 32178109, 32178111, + 32178113, 32178115, 32178117, 32178119, 32178121, 32178123, 32178125, 32178127, 32178129, 32178131, 32178133, 32178135, 32178137, 32178139, 32178141, + 32178143, 32178145, 32178147, 32178149, 32178151, 32178153, 32178155, 32178157, 32178159, 32178161, 32178163, 32178165, 32178167, 32178169, 32178171, + 32178173, 14401, 0, 14400, 32169989, 32169991, 32169993, 32169995, 32169997, 32169999, 32170001, 32170003, 32170005, 32170007, 32170009, + 32170011, 32170013, 32170015, 32170017, 32170019, 32170021, 32170023, 32170025, 32170027, 32170029, 32170031, 32170033, 32170035, 32170037, 32170039, + 32170041, 32170043, 32170045, 32170047, 32170049, 32170051, 32170053, 32170055, 32170057, 32170059, 32170061, 32170063, 32170065, 32170067, 32170069, + 32170071, 32170073, 32170075, 32170077, 32170079, 32170081, 32170083, 32170085, 32170087, 32170089, 32170091, 32170093, 32170095, 32170097, 32170099, + 32170101, 32170103, 32170105, 32170107, 32170109, 32170111, 32194433, 32194435, 32194437, 32194439, 32194441, 32194443, 32194445, 32194447, 32194449, + 32194451, 32194453, 32194455, 32194457, 32194459, 32194461, 32194463, 32194465, 32194467, 32194469, 32194471, 32194473, 32194475, 32194477, 32194479, + 32194481, 32194483, 32194485, 32194487, 32194489, 32194491, 32194493, 32194495, 32194497, 32194499, 32194501, 32194503, 32194505, 32194507, 32194509, + 32194511, 32194513, 32194515, 32194517, 32194519, 32194521, 32194523, 32194525, 32194527, 32194529, 32194531, 32194533, 32194535, 32194537, 32194539, + 32194541, 32194543, 32194545, 32194547, 32194549, 32194551, 32194553, 32194555, 32194557, 14399, 0, 14398, 32186373, 32186375, 32186377, + 32186379, 32186381, 32186383, 32186385, 32186387, 32186389, 32186391, 32186393, 32186395, 32186397, 32186399, 32186401, 32186403, 32186405, 32186407, + 32186409, 32186411, 32186413, 32186415, 32186417, 32186419, 32186421, 32186423, 32186425, 32186427, 32186429, 32186431, 32186433, 32186435, 32186437, + 32186439, 32186441, 32186443, 32186445, 32186447, 32186449, 32186451, 32186453, 32186455, 32186457, 32186459, 32186461, 32186463, 32186465, 32186467, + 32186469, 32186471, 32186473, 32186475, 32186477, 32186479, 32186481, 32186483, 32186485, 32186487, 32186489, 32186491, 32186493, 32186495, 32210817, + 32210819, 32210821, 32210823, 32210825, 32210827, 32210829, 32210831, 32210833, 32210835, 32210837, 32210839, 32210841, 32210843, 32210845, 32210847, + 32210849, 32210851, 32210853, 32210855, 32210857, 32210859, 32210861, 32210863, 32210865, 32210867, 32210869, 32210871, 32210873, 32210875, 32210877, + 32210879, 32210881, 32210883, 32210885, 32210887, 32210889, 32210891, 32210893, 32210895, 32210897, 32210899, 32210901, 32210903, 32210905, 32210907, + 32210909, 32210911, 32210913, 32210915, 32210917, 32210919, 32210921, 32210923, 32210925, 32210927, 32210929, 32210931, 32210933, 32210935, 32210937, + 32210939, 32210941, 14397, 0, 14396, 32202757, 32202759, 32202761, 32202763, 32202765, 32202767, 32202769, 32202771, 32202773, 32202775, + 32202777, 32202779, 32202781, 32202783, 32202785, 32202787, 32202789, 32202791, 32202793, 32202795, 32202797, 32202799, 32202801, 32202803, 32202805, + 32202807, 32202809, 32202811, 32202813, 32202815, 32202817, 32202819, 32202821, 32202823, 32202825, 32202827, 32202829, 32202831, 32202833, 32202835, + 32202837, 32202839, 32202841, 32202843, 32202845, 32202847, 32202849, 32202851, 32202853, 32202855, 32202857, 32202859, 32202861, 32202863, 32202865, + 32202867, 32202869, 32202871, 32202873, 32202875, 32202877, 32202879, 32227201, 32227203, 32227205, 32227207, 32227209, 32227211, 32227213, 32227215, + 32227217, 32227219, 32227221, 32227223, 32227225, 32227227, 32227229, 32227231, 32227233, 32227235, 32227237, 32227239, 32227241, 32227243, 32227245, + 32227247, 32227249, 32227251, 32227253, 32227255, 32227257, 32227259, 32227261, 32227263, 32227265, 32227267, 32227269, 32227271, 32227273, 32227275, + 32227277, 32227279, 32227281, 32227283, 32227285, 32227287, 32227289, 32227291, 32227293, 32227295, 32227297, 32227299, 32227301, 32227303, 32227305, + 32227307, 32227309, 32227311, 32227313, 32227315, 32227317, 32227319, 32227321, 32227323, 32227325, 14395, 0, 14394, 32219141, 32219143, + 32219145, 32219147, 32219149, 32219151, 32219153, 32219155, 32219157, 32219159, 32219161, 32219163, 32219165, 32219167, 32219169, 32219171, 32219173, + 32219175, 32219177, 32219179, 32219181, 32219183, 32219185, 32219187, 32219189, 32219191, 32219193, 32219195, 32219197, 32219199, 32219201, 32219203, + 32219205, 32219207, 32219209, 32219211, 32219213, 32219215, 32219217, 32219219, 32219221, 32219223, 32219225, 32219227, 32219229, 32219231, 32219233, + 32219235, 32219237, 32219239, 32219241, 32219243, 32219245, 32219247, 32219249, 32219251, 32219253, 32219255, 32219257, 32219259, 32219261, 32219263, + 32243585, 32243587, 32243589, 32243591, 32243593, 32243595, 32243597, 32243599, 32243601, 32243603, 32243605, 32243607, 32243609, 32243611, 32243613, + 32243615, 32243617, 32243619, 32243621, 32243623, 32243625, 32243627, 32243629, 32243631, 32243633, 32243635, 32243637, 32243639, 32243641, 32243643, + 32243645, 32243647, 32243649, 32243651, 32243653, 32243655, 32243657, 32243659, 32243661, 32243663, 32243665, 32243667, 32243669, 32243671, 32243673, + 32243675, 32243677, 32243679, 32243681, 32243683, 32243685, 32243687, 32243689, 32243691, 32243693, 32243695, 32243697, 32243699, 32243701, 32243703, + 32243705, 32243707, 32243709, 14393, 0, 14392, 32235525, 32235527, 32235529, 32235531, 32235533, 32235535, 32235537, 32235539, 32235541, + 32235543, 32235545, 32235547, 32235549, 32235551, 32235553, 32235555, 32235557, 32235559, 32235561, 32235563, 32235565, 32235567, 32235569, 32235571, + 32235573, 32235575, 32235577, 32235579, 32235581, 32235583, 32235585, 32235587, 32235589, 32235591, 32235593, 32235595, 32235597, 32235599, 32235601, + 32235603, 32235605, 32235607, 32235609, 32235611, 32235613, 32235615, 32235617, 32235619, 32235621, 32235623, 32235625, 32235627, 32235629, 32235631, + 32235633, 32235635, 32235637, 32235639, 32235641, 32235643, 32235645, 32235647, 32259969, 32259971, 32259973, 32259975, 32259977, 32259979, 32259981, + 32259983, 32259985, 32259987, 32259989, 32259991, 32259993, 32259995, 32259997, 32259999, 32260001, 32260003, 32260005, 32260007, 32260009, 32260011, + 32260013, 32260015, 32260017, 32260019, 32260021, 32260023, 32260025, 32260027, 32260029, 32260031, 32260033, 32260035, 32260037, 32260039, 32260041, + 32260043, 32260045, 32260047, 32260049, 32260051, 32260053, 32260055, 32260057, 32260059, 32260061, 32260063, 32260065, 32260067, 32260069, 32260071, + 32260073, 32260075, 32260077, 32260079, 32260081, 32260083, 32260085, 32260087, 32260089, 32260091, 32260093, 14391, 0, 14390, 32251909, + 32251911, 32251913, 32251915, 32251917, 32251919, 32251921, 32251923, 32251925, 32251927, 32251929, 32251931, 32251933, 32251935, 32251937, 32251939, + 32251941, 32251943, 32251945, 32251947, 32251949, 32251951, 32251953, 32251955, 32251957, 32251959, 32251961, 32251963, 32251965, 32251967, 32251969, + 32251971, 32251973, 32251975, 32251977, 32251979, 32251981, 32251983, 32251985, 32251987, 32251989, 32251991, 32251993, 32251995, 32251997, 32251999, + 32252001, 32252003, 32252005, 32252007, 32252009, 32252011, 32252013, 32252015, 32252017, 32252019, 32252021, 32252023, 32252025, 32252027, 32252029, + 32252031, 32276353, 32276355, 32276357, 32276359, 32276361, 32276363, 32276365, 32276367, 32276369, 32276371, 32276373, 32276375, 32276377, 32276379, + 32276381, 32276383, 32276385, 32276387, 32276389, 32276391, 32276393, 32276395, 32276397, 32276399, 32276401, 32276403, 32276405, 32276407, 32276409, + 32276411, 32276413, 32276415, 32276417, 32276419, 32276421, 32276423, 32276425, 32276427, 32276429, 32276431, 32276433, 32276435, 32276437, 32276439, + 32276441, 32276443, 32276445, 32276447, 32276449, 32276451, 32276453, 32276455, 32276457, 32276459, 32276461, 32276463, 32276465, 32276467, 32276469, + 32276471, 32276473, 32276475, 32276477, 14389, 0, 14388, 32268293, 32268295, 32268297, 32268299, 32268301, 32268303, 32268305, 32268307, + 32268309, 32268311, 32268313, 32268315, 32268317, 32268319, 32268321, 32268323, 32268325, 32268327, 32268329, 32268331, 32268333, 32268335, 32268337, + 32268339, 32268341, 32268343, 32268345, 32268347, 32268349, 32268351, 32268353, 32268355, 32268357, 32268359, 32268361, 32268363, 32268365, 32268367, + 32268369, 32268371, 32268373, 32268375, 32268377, 32268379, 32268381, 32268383, 32268385, 32268387, 32268389, 32268391, 32268393, 32268395, 32268397, + 32268399, 32268401, 32268403, 32268405, 32268407, 32268409, 32268411, 32268413, 32268415, 32292737, 32292739, 32292741, 32292743, 32292745, 32292747, + 32292749, 32292751, 32292753, 32292755, 32292757, 32292759, 32292761, 32292763, 32292765, 32292767, 32292769, 32292771, 32292773, 32292775, 32292777, + 32292779, 32292781, 32292783, 32292785, 32292787, 32292789, 32292791, 32292793, 32292795, 32292797, 32292799, 32292801, 32292803, 32292805, 32292807, + 32292809, 32292811, 32292813, 32292815, 32292817, 32292819, 32292821, 32292823, 32292825, 32292827, 32292829, 32292831, 32292833, 32292835, 32292837, + 32292839, 32292841, 32292843, 32292845, 32292847, 32292849, 32292851, 32292853, 32292855, 32292857, 32292859, 32292861, 57413, 0, 57412, + 32284677, 32284679, 32284681, 32284683, 32284685, 32284687, 32284689, 32284691, 32284693, 32284695, 32284697, 32284699, 32284701, 32284703, 32284705, + 32284707, 32284709, 32284711, 32284713, 32284715, 32284717, 32284719, 32284721, 32284723, 32284725, 32284727, 32284729, 32284731, 32284733, 32284735, + 32284737, 32284739, 32284741, 32284743, 32284745, 32284747, 32284749, 32284751, 32284753, 32284755, 32284757, 32284759, 32284761, 32284763, 32284765, + 32284767, 32284769, 32284771, 32284773, 32284775, 32284777, 32284779, 32284781, 32284783, 32284785, 32284787, 32284789, 32284791, 32284793, 32284795, + 32284797, 32284799, 32309121, 32309123, 32309125, 32309127, 32309129, 32309131, 32309133, 32309135, 32309137, 32309139, 32309141, 32309143, 32309145, + 32309147, 32309149, 32309151, 32309153, 32309155, 32309157, 32309159, 32309161, 32309163, 32309165, 32309167, 32309169, 32309171, 32309173, 32309175, + 32309177, 32309179, 32309181, 32309183, 32309185, 32309187, 32309189, 32309191, 32309193, 32309195, 32309197, 32309199, 32309201, 32309203, 32309205, + 32309207, 32309209, 32309211, 32309213, 32309215, 32309217, 32309219, 32309221, 32309223, 32309225, 32309227, 32309229, 32309231, 32309233, 32309235, + 32309237, 32309239, 32309241, 32309243, 32309245, 57415, 0, 57414, 32301061, 32301063, 32301065, 32301067, 32301069, 32301071, 32301073, + 32301075, 32301077, 32301079, 32301081, 32301083, 32301085, 32301087, 32301089, 32301091, 32301093, 32301095, 32301097, 32301099, 32301101, 32301103, + 32301105, 32301107, 32301109, 32301111, 32301113, 32301115, 32301117, 32301119, 32301121, 32301123, 32301125, 32301127, 32301129, 32301131, 32301133, + 32301135, 32301137, 32301139, 32301141, 32301143, 32301145, 32301147, 32301149, 32301151, 32301153, 32301155, 32301157, 32301159, 32301161, 32301163, + 32301165, 32301167, 32301169, 32301171, 32301173, 32301175, 32301177, 32301179, 32301181, 32301183, 32325505, 32325507, 32325509, 32325511, 32325513, + 32325515, 32325517, 32325519, 32325521, 32325523, 32325525, 32325527, 32325529, 32325531, 32325533, 32325535, 32325537, 32325539, 32325541, 32325543, + 32325545, 32325547, 32325549, 32325551, 32325553, 32325555, 32325557, 32325559, 32325561, 32325563, 32325565, 32325567, 32325569, 32325571, 32325573, + 32325575, 32325577, 32325579, 32325581, 32325583, 32325585, 32325587, 32325589, 32325591, 32325593, 32325595, 32325597, 32325599, 32325601, 32325603, + 32325605, 32325607, 32325609, 32325611, 32325613, 32325615, 32325617, 32325619, 32325621, 32325623, 32325625, 32325627, 32325629, 114861, 0, + 114860, 32317445, 32317447, 32317449, 32317451, 32317453, 32317455, 32317457, 32317459, 32317461, 32317463, 32317465, 32317467, 32317469, 32317471, + 32317473, 32317475, 32317477, 32317479, 32317481, 32317483, 32317485, 32317487, 32317489, 32317491, 32317493, 32317495, 32317497, 32317499, 32317501, + 32317503, 32317505, 32317507, 32317509, 32317511, 32317513, 32317515, 32317517, 32317519, 32317521, 32317523, 32317525, 32317527, 32317529, 32317531, + 32317533, 32317535, 32317537, 32317539, 32317541, 32317543, 32317545, 32317547, 32317549, 32317551, 32317553, 32317555, 32317557, 32317559, 32317561, + 32317563, 32317565, 32317567, 32341889, 32341891, 32341893, 32341895, 32341897, 32341899, 32341901, 32341903, 32341905, 32341907, 32341909, 32341911, + 32341913, 32341915, 32341917, 32341919, 32341921, 32341923, 32341925, 32341927, 32341929, 32341931, 32341933, 32341935, 32341937, 32341939, 32341941, + 32341943, 32341945, 32341947, 32341949, 32341951, 32341953, 32341955, 32341957, 32341959, 32341961, 32341963, 32341965, 32341967, 32341969, 32341971, + 32341973, 32341975, 32341977, 32341979, 32341981, 32341983, 32341985, 32341987, 32341989, 32341991, 32341993, 32341995, 32341997, 32341999, 32342001, + 32342003, 32342005, 32342007, 32342009, 32342011, 32342013, 114863, 0, 114862, 32333829, 32333831, 32333833, 32333835, 32333837, 32333839, + 32333841, 32333843, 32333845, 32333847, 32333849, 32333851, 32333853, 32333855, 32333857, 32333859, 32333861, 32333863, 32333865, 32333867, 32333869, + 32333871, 32333873, 32333875, 32333877, 32333879, 32333881, 32333883, 32333885, 32333887, 32333889, 32333891, 32333893, 32333895, 32333897, 32333899, + 32333901, 32333903, 32333905, 32333907, 32333909, 32333911, 32333913, 32333915, 32333917, 32333919, 32333921, 32333923, 32333925, 32333927, 32333929, + 32333931, 32333933, 32333935, 32333937, 32333939, 32333941, 32333943, 32333945, 32333947, 32333949, 32333951, 32358273, 32358275, 32358277, 32358279, + 32358281, 32358283, 32358285, 32358287, 32358289, 32358291, 32358293, 32358295, 32358297, 32358299, 32358301, 32358303, 32358305, 32358307, 32358309, + 32358311, 32358313, 32358315, 32358317, 32358319, 32358321, 32358323, 32358325, 32358327, 32358329, 32358331, 32358333, 32358335, 32358337, 32358339, + 32358341, 32358343, 32358345, 32358347, 32358349, 32358351, 32358353, 32358355, 32358357, 32358359, 32358361, 32358363, 32358365, 32358367, 32358369, + 32358371, 32358373, 32358375, 32358377, 32358379, 32358381, 32358383, 32358385, 32358387, 32358389, 32358391, 32358393, 32358395, 32358397, 32358399, + 0, 32350211, 32350213, 32350215, 32350217, 32350219, 32350221, 32350223, 32350225, 32350227, 32350229, 32350231, 32350233, 32350235, 32350237, + 32350239, 32350241, 32350243, 32350245, 32350247, 32350249, 32350251, 32350253, 32350255, 32350257, 32350259, 32350261, 32350263, 32350265, 32350267, + 32350269, 32350271, 32350273, 32350275, 32350277, 32350279, 32350281, 32350283, 32350285, 32350287, 32350289, 32350291, 32350293, 32350295, 32350297, + 32350299, 32350301, 32350303, 32350305, 32350307, 32350309, 32350311, 32350313, 32350315, 32350317, 32350319, 32350321, 32350323, 32350325, 32350327, + 32350329, 32350331, 32350333, 32350335, 32374657, 32374659, 32374661, 32374663, 32374665, 32374667, 32374669, 32374671, 32374673, 32374675, 32374677, + 32374679, 32374681, 32374683, 32374685, 32374687, 32374689, 32374691, 32374693, 32374695, 32374697, 32374699, 32374701, 32374703, 32374705, 32374707, + 32374709, 32374711, 32374713, 32374715, 32374717, 32374719, 32374721, 32374723, 32374725, 32374727, 32374729, 32374731, 32374733, 32374735, 32374737, + 32374739, 32374741, 32374743, 32374745, 32374747, 32374749, 32374751, 32374753, 32374755, 32374757, 32374759, 32374761, 32374763, 32374765, 32374767, + 32374769, 32374771, 32374773, 32374775, 32374777, 32374779, 32374781, 32374783, 0, 32366595, 32366597, 32366599, 32366601, 32366603, 32366605, + 32366607, 32366609, 32366611, 32366613, 32366615, 32366617, 32366619, 32366621, 32366623, 32366625, 32366627, 32366629, 32366631, 32366633, 32366635, + 32366637, 32366639, 32366641, 32366643, 32366645, 32366647, 32366649, 32366651, 32366653, 32366655, 32366657, 32366659, 32366661, 32366663, 32366665, + 32366667, 32366669, 32366671, 32366673, 32366675, 32366677, 32366679, 32366681, 32366683, 32366685, 32366687, 32366689, 32366691, 32366693, 32366695, + 32366697, 32366699, 32366701, 32366703, 32366705, 32366707, 32366709, 32366711, 32366713, 32366715, 32366717, 32366719, 32391041, 32391043, 32391045, + 32391047, 32391049, 32391051, 32391053, 32391055, 32391057, 32391059, 32391061, 32391063, 32391065, 32391067, 32391069, 32391071, 32391073, 32391075, + 32391077, 32391079, 32391081, 32391083, 32391085, 32391087, 32391089, 32391091, 32391093, 32391095, 32391097, 32391099, 32391101, 32391103, 32391105, + 32391107, 32391109, 32391111, 32391113, 32391115, 32391117, 32391119, 32391121, 32391123, 32391125, 32391127, 32391129, 32391131, 32391133, 32391135, + 32391137, 32391139, 32391141, 32391143, 32391145, 32391147, 32391149, 32391151, 32391153, 32391155, 32391157, 32391159, 32391161, 32391163, 32391165, + 32391167, 0, 32382979, 32382981, 32382983, 32382985, 32382987, 32382989, 32382991, 32382993, 32382995, 32382997, 32382999, 32383001, 32383003, + 32383005, 32383007, 32383009, 32383011, 32383013, 32383015, 32383017, 32383019, 32383021, 32383023, 32383025, 32383027, 32383029, 32383031, 32383033, + 32383035, 32383037, 32383039, 32383041, 32383043, 32383045, 32383047, 32383049, 32383051, 32383053, 32383055, 32383057, 32383059, 32383061, 32383063, + 32383065, 32383067, 32383069, 32383071, 32383073, 32383075, 32383077, 32383079, 32383081, 32383083, 32383085, 32383087, 32383089, 32383091, 32383093, + 32383095, 32383097, 32383099, 32383101, 32383103, 32407425, 32407427, 32407429, 32407431, 32407433, 32407435, 32407437, 32407439, 32407441, 32407443, + 32407445, 32407447, 32407449, 32407451, 32407453, 32407455, 32407457, 32407459, 32407461, 32407463, 32407465, 32407467, 32407469, 32407471, 32407473, + 32407475, 32407477, 32407479, 32407481, 32407483, 32407485, 32407487, 32407489, 32407491, 32407493, 32407495, 32407497, 32407499, 32407501, 32407503, + 32407505, 32407507, 32407509, 32407511, 32407513, 32407515, 32407517, 32407519, 32407521, 32407523, 32407525, 32407527, 32407529, 32407531, 32407533, + 32407535, 32407537, 32407539, 32407541, 32407543, 32407545, 32407547, 32407549, 32407551, 0, 32399363, 32399365, 32399367, 32399369, 32399371, + 32399373, 32399375, 32399377, 32399379, 32399381, 32399383, 32399385, 32399387, 32399389, 32399391, 32399393, 32399395, 32399397, 32399399, 32399401, + 32399403, 32399405, 32399407, 32399409, 32399411, 32399413, 32399415, 32399417, 32399419, 32399421, 32399423, 32399425, 32399427, 32399429, 32399431, + 32399433, 32399435, 32399437, 32399439, 32399441, 32399443, 32399445, 32399447, 32399449, 32399451, 32399453, 32399455, 32399457, 32399459, 32399461, + 32399463, 32399465, 32399467, 32399469, 32399471, 32399473, 32399475, 32399477, 32399479, 32399481, 32399483, 32399485, 32399487, 32423809, 32423811, + 32423813, 32423815, 32423817, 32423819, 32423821, 32423823, 32423825, 32423827, 32423829, 32423831, 32423833, 32423835, 32423837, 32423839, 32423841, + 32423843, 32423845, 32423847, 32423849, 32423851, 32423853, 32423855, 32423857, 32423859, 32423861, 32423863, 32423865, 32423867, 32423869, 32423871, + 32423873, 32423875, 32423877, 32423879, 32423881, 32423883, 32423885, 32423887, 32423889, 32423891, 32423893, 32423895, 32423897, 32423899, 32423901, + 32423903, 32423905, 32423907, 32423909, 32423911, 32423913, 32423915, 32423917, 32423919, 32423921, 32423923, 32423925, 32423927, 32423929, 32423931, + 32423933, 32423935, 0, 32415747, 32415749, 32415751, 32415753, 32415755, 32415757, 32415759, 32415761, 32415763, 32415765, 32415767, 32415769, + 32415771, 32415773, 32415775, 32415777, 32415779, 32415781, 32415783, 32415785, 32415787, 32415789, 32415791, 32415793, 32415795, 32415797, 32415799, + 32415801, 32415803, 32415805, 32415807, 32415809, 32415811, 32415813, 32415815, 32415817, 32415819, 32415821, 32415823, 32415825, 32415827, 32415829, + 32415831, 32415833, 32415835, 32415837, 32415839, 32415841, 32415843, 32415845, 32415847, 32415849, 32415851, 32415853, 32415855, 32415857, 32415859, + 32415861, 32415863, 32415865, 32415867, 32415869, 32415871, 32440193, 32440195, 32440197, 32440199, 32440201, 32440203, 32440205, 32440207, 32440209, + 32440211, 32440213, 32440215, 32440217, 32440219, 32440221, 32440223, 32440225, 32440227, 32440229, 32440231, 32440233, 32440235, 32440237, 32440239, + 32440241, 32440243, 32440245, 32440247, 32440249, 32440251, 32440253, 32440255, 32440257, 32440259, 32440261, 32440263, 32440265, 32440267, 32440269, + 32440271, 32440273, 32440275, 32440277, 32440279, 32440281, 32440283, 32440285, 32440287, 32440289, 32440291, 32440293, 32440295, 32440297, 32440299, + 32440301, 32440303, 32440305, 32440307, 32440309, 32440311, 32440313, 32440315, 32440317, 32440319, 0, 32432131, 32432133, 32432135, 32432137, + 32432139, 32432141, 32432143, 32432145, 32432147, 32432149, 32432151, 32432153, 32432155, 32432157, 32432159, 32432161, 32432163, 32432165, 32432167, + 32432169, 32432171, 32432173, 32432175, 32432177, 32432179, 32432181, 32432183, 32432185, 32432187, 32432189, 32432191, 32432193, 32432195, 32432197, + 32432199, 32432201, 32432203, 32432205, 32432207, 32432209, 32432211, 32432213, 32432215, 32432217, 32432219, 32432221, 32432223, 32432225, 32432227, + 32432229, 32432231, 32432233, 32432235, 32432237, 32432239, 32432241, 32432243, 32432245, 32432247, 32432249, 32432251, 32432253, 32432255, 32456577, + 32456579, 32456581, 32456583, 32456585, 32456587, 32456589, 32456591, 32456593, 32456595, 32456597, 32456599, 32456601, 32456603, 32456605, 32456607, + 32456609, 32456611, 32456613, 32456615, 32456617, 32456619, 32456621, 32456623, 32456625, 32456627, 32456629, 32456631, 32456633, 32456635, 32456637, + 32456639, 32456641, 32456643, 32456645, 32456647, 32456649, 32456651, 32456653, 32456655, 32456657, 32456659, 32456661, 32456663, 32456665, 32456667, + 32456669, 32456671, 32456673, 32456675, 32456677, 32456679, 32456681, 32456683, 32456685, 32456687, 32456689, 32456691, 32456693, 32456695, 32456697, + 32456699, 32456701, 32456703, 0, 32448515, 32448517, 32448519, 32448521, 32448523, 32448525, 32448527, 32448529, 32448531, 32448533, 32448535, + 32448537, 32448539, 32448541, 32448543, 32448545, 32448547, 32448549, 32448551, 32448553, 32448555, 32448557, 32448559, 32448561, 32448563, 32448565, + 32448567, 32448569, 32448571, 32448573, 32448575, 32448577, 32448579, 32448581, 32448583, 32448585, 32448587, 32448589, 32448591, 32448593, 32448595, + 32448597, 32448599, 32448601, 32448603, 32448605, 32448607, 32448609, 32448611, 32448613, 32448615, 32448617, 32448619, 32448621, 32448623, 32448625, + 32448627, 32448629, 32448631, 32448633, 32448635, 32448637, 32448639, 32472961, 32472963, 32472965, 32472967, 32472969, 32472971, 32472973, 32472975, + 32472977, 32472979, 32472981, 32472983, 32472985, 32472987, 32472989, 32472991, 32472993, 32472995, 32472997, 32472999, 32473001, 32473003, 32473005, + 32473007, 32473009, 32473011, 32473013, 32473015, 32473017, 32473019, 32473021, 32473023, 32473025, 32473027, 32473029, 32473031, 32473033, 32473035, + 32473037, 32473039, 32473041, 32473043, 32473045, 32473047, 32473049, 32473051, 32473053, 32473055, 32473057, 32473059, 32473061, 32473063, 32473065, + 32473067, 32473069, 32473071, 32473073, 32473075, 32473077, 32473079, 32473081, 32473083, 32473085, 32473087, 0, 32464899, 32464901, 32464903, + 32464905, 32464907, 32464909, 32464911, 32464913, 32464915, 32464917, 32464919, 32464921, 32464923, 32464925, 32464927, 32464929, 32464931, 32464933, + 32464935, 32464937, 32464939, 32464941, 32464943, 32464945, 32464947, 32464949, 32464951, 32464953, 32464955, 32464957, 32464959, 32464961, 32464963, + 32464965, 32464967, 32464969, 32464971, 32464973, 32464975, 32464977, 32464979, 32464981, 32464983, 32464985, 32464987, 32464989, 32464991, 32464993, + 32464995, 32464997, 32464999, 32465001, 32465003, 32465005, 32465007, 32465009, 32465011, 32465013, 32465015, 32465017, 32465019, 32465021, 32465023, + 32489345, 32489347, 32489349, 32489351, 32489353, 32489355, 32489357, 32489359, 32489361, 32489363, 32489365, 32489367, 32489369, 32489371, 32489373, + 32489375, 32489377, 32489379, 32489381, 32489383, 32489385, 32489387, 32489389, 32489391, 32489393, 32489395, 32489397, 32489399, 32489401, 32489403, + 32489405, 32489407, 32489409, 32489411, 32489413, 32489415, 32489417, 32489419, 32489421, 32489423, 32489425, 32489427, 32489429, 32489431, 32489433, + 32489435, 32489437, 32489439, 32489441, 32489443, 32489445, 32489447, 32489449, 32489451, 32489453, 32489455, 32489457, 32489459, 32489461, 32489463, + 32489465, 32489467, 32489469, 32489471, 0, 32481283, 32481285, 32481287, 32481289, 32481291, 32481293, 32481295, 32481297, 32481299, 32481301, + 32481303, 32481305, 32481307, 32481309, 32481311, 32481313, 32481315, 32481317, 32481319, 32481321, 32481323, 32481325, 32481327, 32481329, 32481331, + 32481333, 32481335, 32481337, 32481339, 32481341, 32481343, 32481345, 32481347, 32481349, 32481351, 32481353, 32481355, 32481357, 32481359, 32481361, + 32481363, 32481365, 32481367, 32481369, 32481371, 32481373, 32481375, 32481377, 32481379, 32481381, 32481383, 32481385, 32481387, 32481389, 32481391, + 32481393, 32481395, 32481397, 32481399, 32481401, 32481403, 32481405, 32481407, 32505729, 32505731, 32505733, 32505735, 32505737, 32505739, 32505741, + 32505743, 32505745, 32505747, 32505749, 32505751, 32505753, 32505755, 32505757, 32505759, 32505761, 32505763, 32505765, 32505767, 32505769, 32505771, + 32505773, 32505775, 32505777, 32505779, 32505781, 32505783, 32505785, 32505787, 32505789, 32505791, 32505793, 32505795, 32505797, 32505799, 32505801, + 32505803, 32505805, 32505807, 32505809, 32505811, 32505813, 32505815, 32505817, 32505819, 32505821, 32505823, 32505825, 32505827, 32505829, 32505831, + 32505833, 32505835, 32505837, 32505839, 32505841, 32505843, 32505845, 32505847, 32505849, 32505851, 32505853, 32505855, 0, 32497667, 32497669, + 32497671, 32497673, 32497675, 32497677, 32497679, 32497681, 32497683, 32497685, 32497687, 32497689, 32497691, 32497693, 32497695, 32497697, 32497699, + 32497701, 32497703, 32497705, 32497707, 32497709, 32497711, 32497713, 32497715, 32497717, 32497719, 32497721, 32497723, 32497725, 32497727, 32497729, + 32497731, 32497733, 32497735, 32497737, 32497739, 32497741, 32497743, 32497745, 32497747, 32497749, 32497751, 32497753, 32497755, 32497757, 32497759, + 32497761, 32497763, 32497765, 32497767, 32497769, 32497771, 32497773, 32497775, 32497777, 32497779, 32497781, 32497783, 32497785, 32497787, 32497789, + 32497791, 32522113, 32522115, 32522117, 32522119, 32522121, 32522123, 32522125, 32522127, 32522129, 32522131, 32522133, 32522135, 32522137, 32522139, + 32522141, 32522143, 32522145, 32522147, 32522149, 32522151, 32522153, 32522155, 32522157, 32522159, 32522161, 32522163, 32522165, 32522167, 32522169, + 32522171, 32522173, 32522175, 32522177, 32522179, 32522181, 32522183, 32522185, 32522187, 32522189, 32522191, 32522193, 32522195, 32522197, 32522199, + 32522201, 32522203, 32522205, 32522207, 32522209, 32522211, 32522213, 32522215, 32522217, 32522219, 32522221, 32522223, 32522225, 32522227, 24587, + 6195, 207, 11, 51, 15, 0, 14, 50, 10, 206, 6194, 24586, 32514063, 32514065, 32514067, + 32514069, 32514071, 32514073, 32514075, 32514077, 32514079, 32514081, 32514083, 32514085, 32514087, 32514089, 32514091, 32514093, 32514095, 32514097, + 32514099, 32514101, 32514103, 32514105, 32514107, 32514109, 32514111, 32514113, 32514115, 32514117, 32514119, 32514121, 32514123, 32514125, 32514127, + 32514129, 32514131, 32514133, 32514135, 32514137, 32514139, 32514141, 32514143, 32514145, 32514147, 32514149, 32514151, 32514153, 32514155, 32514157, + 32514159, 32514161, 32514163, 32514165, 32514167, 32514169, 32514171, 32514173, 32514175, 32538497, 32538499, 32538501, 32538503, 32538505, 32538507, + 32538509, 32538511, 32538513, 32538515, 32538517, 32538519, 32538521, 32538523, 32538525, 32538527, 32538529, 32538531, 32538533, 32538535, 32538537, + 32538539, 32538541, 32538543, 32538545, 32538547, 32538549, 32538551, 32538553, 32538555, 32538557, 32538559, 32538561, 32538563, 32538565, 32538567, + 32538569, 32538571, 32538573, 32538575, 32538577, 32538579, 32538581, 32538583, 32538585, 32538587, 32538589, 32538591, 32538593, 32538595, 32538597, + 32538599, 32538601, 32538603, 32538605, 32538607, 32538609, 32538611, 32538613, 32538615, 24585, 799, 9, 31, 0, 30, + 8, 798, 24584, 32530443, 32530445, 32530447, 32530449, 32530451, 32530453, 32530455, 32530457, 32530459, 32530461, 32530463, 32530465, + 32530467, 32530469, 32530471, 32530473, 32530475, 32530477, 32530479, 32530481, 32530483, 32530485, 32530487, 32530489, 32530491, 32530493, 32530495, + 32530497, 32530499, 32530501, 32530503, 32530505, 32530507, 32530509, 32530511, 32530513, 32530515, 32530517, 32530519, 32530521, 32530523, 32530525, + 32530527, 32530529, 32530531, 32530533, 32530535, 32530537, 32530539, 32530541, 32530543, 32530545, 32530547, 32530549, 32530551, 32530553, 32530555, + 32530557, 32530559, 32554881, 32554883, 32554885, 32554887, 32554889, 32554891, 32554893, 32554895, 32554897, 32554899, 32554901, 32554903, 32554905, + 32554907, 32554909, 32554911, 32554913, 32554915, 32554917, 32554919, 32554921, 32554923, 32554925, 32554927, 32554929, 32554931, 32554933, 32554935, + 32554937, 32554939, 32554941, 32554943, 32554945, 32554947, 32554949, 32554951, 32554953, 32554955, 32554957, 32554959, 32554961, 32554963, 32554965, + 32554967, 32554969, 32554971, 32554973, 32554975, 32554977, 32554979, 32554981, 32554983, 32554985, 32554987, 32554989, 32554991, 32554993, 32554995, + 32554997, 32554999, 32555001, 32555003, 797, 29, 0, 28, 796, 32546823, 32546825, 32546827, 32546829, 32546831, 32546833, + 32546835, 32546837, 32546839, 32546841, 32546843, 32546845, 32546847, 32546849, 32546851, 32546853, 32546855, 32546857, 32546859, 32546861, 32546863, + 32546865, 32546867, 32546869, 32546871, 32546873, 32546875, 32546877, 32546879, 32546881, 32546883, 32546885, 32546887, 32546889, 32546891, 32546893, + 32546895, 32546897, 32546899, 32546901, 32546903, 32546905, 32546907, 32546909, 32546911, 32546913, 32546915, 32546917, 32546919, 32546921, 32546923, + 32546925, 32546927, 32546929, 32546931, 32546933, 32546935, 32546937, 32546939, 32546941, 32546943, 32571265, 32571267, 32571269, 32571271, 32571273, + 32571275, 32571277, 32571279, 32571281, 32571283, 32571285, 32571287, 32571289, 32571291, 32571293, 32571295, 32571297, 32571299, 32571301, 32571303, + 32571305, 32571307, 32571309, 32571311, 32571313, 32571315, 32571317, 32571319, 32571321, 32571323, 32571325, 32571327, 32571329, 32571331, 32571333, + 32571335, 32571337, 32571339, 32571341, 32571343, 32571345, 32571347, 32571349, 32571351, 32571353, 32571355, 32571357, 32571359, 32571361, 32571363, + 32571365, 32571367, 32571369, 32571371, 32571373, 32571375, 32571377, 32571379, 32571381, 32571383, 32571385, 32571387, 795, 27, 0, + 26, 794, 32563207, 32563209, 32563211, 32563213, 32563215, 32563217, 32563219, 32563221, 32563223, 32563225, 32563227, 32563229, 32563231, + 32563233, 32563235, 32563237, 32563239, 32563241, 32563243, 32563245, 32563247, 32563249, 32563251, 32563253, 32563255, 32563257, 32563259, 32563261, + 32563263, 32563265, 32563267, 32563269, 32563271, 32563273, 32563275, 32563277, 32563279, 32563281, 32563283, 32563285, 32563287, 32563289, 32563291, + 32563293, 32563295, 32563297, 32563299, 32563301, 32563303, 32563305, 32563307, 32563309, 32563311, 32563313, 32563315, 32563317, 32563319, 32563321, + 32563323, 32563325, 32563327, 32587649, 32587651, 32587653, 32587655, 32587657, 32587659, 32587661, 32587663, 32587665, 32587667, 32587669, 32587671, + 32587673, 32587675, 32587677, 32587679, 32587681, 32587683, 32587685, 32587687, 32587689, 32587691, 32587693, 32587695, 32587697, 32587699, 32587701, + 32587703, 32587705, 32587707, 32587709, 32587711, 32587713, 32587715, 32587717, 32587719, 32587721, 32587723, 32587725, 32587727, 32587729, 32587731, + 32587733, 32587735, 32587737, 32587739, 32587741, 32587743, 32587745, 32587747, 32587749, 32587751, 32587753, 32587755, 32587757, 32587759, 32587761, + 32587763, 32587765, 32587767, 32587769, 32587771, 793, 25, 0, 24, 792, 32579591, 32579593, 32579595, 32579597, 32579599, + 32579601, 32579603, 32579605, 32579607, 32579609, 32579611, 32579613, 32579615, 32579617, 32579619, 32579621, 32579623, 32579625, 32579627, 32579629, + 32579631, 32579633, 32579635, 32579637, 32579639, 32579641, 32579643, 32579645, 32579647, 32579649, 32579651, 32579653, 32579655, 32579657, 32579659, + 32579661, 32579663, 32579665, 32579667, 32579669, 32579671, 32579673, 32579675, 32579677, 32579679, 32579681, 32579683, 32579685, 32579687, 32579689, + 32579691, 32579693, 32579695, 32579697, 32579699, 32579701, 32579703, 32579705, 32579707, 32579709, 32579711, 32604033, 32604035, 32604037, 32604039, + 32604041, 32604043, 32604045, 32604047, 32604049, 32604051, 32604053, 32604055, 32604057, 32604059, 32604061, 32604063, 32604065, 32604067, 32604069, + 32604071, 32604073, 32604075, 32604077, 32604079, 32604081, 32604083, 32604085, 32604087, 32604089, 32604091, 32604093, 32604095, 32604097, 32604099, + 32604101, 32604103, 32604105, 32604107, 32604109, 32604111, 32604113, 32604115, 32604117, 32604119, 32604121, 32604123, 32604125, 32604127, 32604129, + 32604131, 32604133, 32604135, 32604137, 32604139, 32604141, 32604143, 32604145, 32604147, 32604149, 32604151, 32604153, 32604155, 1575, 39, + 0, 38, 1574, 32595975, 32595977, 32595979, 32595981, 32595983, 32595985, 32595987, 32595989, 32595991, 32595993, 32595995, 32595997, + 32595999, 32596001, 32596003, 32596005, 32596007, 32596009, 32596011, 32596013, 32596015, 32596017, 32596019, 32596021, 32596023, 32596025, 32596027, + 32596029, 32596031, 32596033, 32596035, 32596037, 32596039, 32596041, 32596043, 32596045, 32596047, 32596049, 32596051, 32596053, 32596055, 32596057, + 32596059, 32596061, 32596063, 32596065, 32596067, 32596069, 32596071, 32596073, 32596075, 32596077, 32596079, 32596081, 32596083, 32596085, 32596087, + 32596089, 32596091, 32596093, 32596095, 32620417, 32620419, 32620421, 32620423, 32620425, 32620427, 32620429, 32620431, 32620433, 32620435, 32620437, + 32620439, 32620441, 32620443, 32620445, 32620447, 32620449, 32620451, 32620453, 32620455, 32620457, 32620459, 32620461, 32620463, 32620465, 32620467, + 32620469, 32620471, 32620473, 32620475, 32620477, 32620479, 32620481, 32620483, 32620485, 32620487, 32620489, 32620491, 32620493, 32620495, 32620497, + 32620499, 32620501, 32620503, 32620505, 32620507, 32620509, 32620511, 32620513, 32620515, 32620517, 32620519, 32620521, 32620523, 32620525, 32620527, + 32620529, 32620531, 32620533, 32620535, 32620537, 32620539, 1573, 37, 0, 36, 1572, 32612359, 32612361, 32612363, 32612365, + 32612367, 32612369, 32612371, 32612373, 32612375, 32612377, 32612379, 32612381, 32612383, 32612385, 32612387, 32612389, 32612391, 32612393, 32612395, + 32612397, 32612399, 32612401, 32612403, 32612405, 32612407, 32612409, 32612411, 32612413, 32612415, 32612417, 32612419, 32612421, 32612423, 32612425, + 32612427, 32612429, 32612431, 32612433, 32612435, 32612437, 32612439, 32612441, 32612443, 32612445, 32612447, 32612449, 32612451, 32612453, 32612455, + 32612457, 32612459, 32612461, 32612463, 32612465, 32612467, 32612469, 32612471, 32612473, 32612475, 32612477, 32612479, 32636801, 32636803, 32636805, + 32636807, 32636809, 32636811, 32636813, 32636815, 32636817, 32636819, 32636821, 32636823, 32636825, 32636827, 32636829, 32636831, 32636833, 32636835, + 32636837, 32636839, 32636841, 32636843, 32636845, 32636847, 32636849, 32636851, 32636853, 32636855, 32636857, 32636859, 32636861, 32636863, 32636865, + 32636867, 32636869, 32636871, 32636873, 32636875, 32636877, 32636879, 32636881, 32636883, 32636885, 32636887, 32636889, 32636891, 32636893, 32636895, + 32636897, 32636899, 32636901, 32636903, 32636905, 32636907, 32636909, 32636911, 32636913, 32636915, 32636917, 32636919, 32636921, 32636923, 1571, + 35, 0, 34, 1570, 32628743, 32628745, 32628747, 32628749, 32628751, 32628753, 32628755, 32628757, 32628759, 32628761, 32628763, + 32628765, 32628767, 32628769, 32628771, 32628773, 32628775, 32628777, 32628779, 32628781, 32628783, 32628785, 32628787, 32628789, 32628791, 32628793, + 32628795, 32628797, 32628799, 32628801, 32628803, 32628805, 32628807, 32628809, 32628811, 32628813, 32628815, 32628817, 32628819, 32628821, 32628823, + 32628825, 32628827, 32628829, 32628831, 32628833, 32628835, 32628837, 32628839, 32628841, 32628843, 32628845, 32628847, 32628849, 32628851, 32628853, + 32628855, 32628857, 32628859, 32628861, 32628863, 32653185, 32653187, 32653189, 32653191, 32653193, 32653195, 32653197, 32653199, 32653201, 32653203, + 32653205, 32653207, 32653209, 32653211, 32653213, 32653215, 32653217, 32653219, 32653221, 32653223, 32653225, 32653227, 32653229, 32653231, 32653233, + 32653235, 32653237, 32653239, 32653241, 32653243, 32653245, 32653247, 32653249, 32653251, 32653253, 32653255, 32653257, 32653259, 32653261, 32653263, + 32653265, 32653267, 32653269, 32653271, 32653273, 32653275, 32653277, 32653279, 32653281, 32653283, 32653285, 32653287, 32653289, 32653291, 32653293, + 32653295, 32653297, 32653299, 32653301, 32653303, 32653305, 32653307, 1569, 33, 0, 32, 1568, 32645127, 32645129, 32645131, + 32645133, 32645135, 32645137, 32645139, 32645141, 32645143, 32645145, 32645147, 32645149, 32645151, 32645153, 32645155, 32645157, 32645159, 32645161, + 32645163, 32645165, 32645167, 32645169, 32645171, 32645173, 32645175, 32645177, 32645179, 32645181, 32645183, 32645185, 32645187, 32645189, 32645191, + 32645193, 32645195, 32645197, 32645199, 32645201, 32645203, 32645205, 32645207, 32645209, 32645211, 32645213, 32645215, 32645217, 32645219, 32645221, + 32645223, 32645225, 32645227, 32645229, 32645231, 32645233, 32645235, 32645237, 32645239, 32645241, 32645243, 32645245, 32645247, 32669569, 32669571, + 32669573, 32669575, 32669577, 32669579, 32669581, 32669583, 32669585, 32669587, 32669589, 32669591, 32669593, 32669595, 32669597, 32669599, 32669601, + 32669603, 32669605, 32669607, 32669609, 32669611, 32669613, 32669615, 32669617, 32669619, 32669621, 32669623, 32669625, 32669627, 32669629, 32669631, + 32669633, 32669635, 32669637, 32669639, 32669641, 32669643, 32669645, 32669647, 32669649, 32669651, 32669653, 32669655, 32669657, 32669659, 32669661, + 32669663, 32669665, 32669667, 32669669, 32669671, 32669673, 32669675, 32669677, 32669679, 32669681, 32669683, 32669685, 32669687, 32669689, 32669691, + 3125, 53, 0, 52, 3124, 32661511, 32661513, 32661515, 32661517, 32661519, 32661521, 32661523, 32661525, 32661527, 32661529, + 32661531, 32661533, 32661535, 32661537, 32661539, 32661541, 32661543, 32661545, 32661547, 32661549, 32661551, 32661553, 32661555, 32661557, 32661559, + 32661561, 32661563, 32661565, 32661567, 32661569, 32661571, 32661573, 32661575, 32661577, 32661579, 32661581, 32661583, 32661585, 32661587, 32661589, + 32661591, 32661593, 32661595, 32661597, 32661599, 32661601, 32661603, 32661605, 32661607, 32661609, 32661611, 32661613, 32661615, 32661617, 32661619, + 32661621, 32661623, 32661625, 32661627, 32661629, 32661631, 32685953, 32685955, 32685957, 32685959, 32685961, 32685963, 32685965, 32685967, 32685969, + 32685971, 32685973, 32685975, 32685977, 32685979, 32685981, 32685983, 32685985, 32685987, 32685989, 32685991, 32685993, 32685995, 32685997, 32685999, + 32686001, 32686003, 32686005, 32686007, 32686009, 32686011, 32686013, 32686015, 32686017, 32686019, 32686021, 32686023, 32686025, 32686027, 32686029, + 32686031, 32686033, 32686035, 32686037, 32686039, 32686041, 32686043, 32686045, 32686047, 32686049, 32686051, 32686053, 32686055, 32686057, 32686059, + 32686061, 32686063, 32686065, 32686067, 32686069, 32686071, 32686073, 32686075, 3123, 51, 0, 50, 3122, 32677895, 32677897, + 32677899, 32677901, 32677903, 32677905, 32677907, 32677909, 32677911, 32677913, 32677915, 32677917, 32677919, 32677921, 32677923, 32677925, 32677927, + 32677929, 32677931, 32677933, 32677935, 32677937, 32677939, 32677941, 32677943, 32677945, 32677947, 32677949, 32677951, 32677953, 32677955, 32677957, + 32677959, 32677961, 32677963, 32677965, 32677967, 32677969, 32677971, 32677973, 32677975, 32677977, 32677979, 32677981, 32677983, 32677985, 32677987, + 32677989, 32677991, 32677993, 32677995, 32677997, 32677999, 32678001, 32678003, 32678005, 32678007, 32678009, 32678011, 32678013, 32678015, 32702337, + 32702339, 32702341, 32702343, 32702345, 32702347, 32702349, 32702351, 32702353, 32702355, 32702357, 32702359, 32702361, 32702363, 32702365, 32702367, + 32702369, 32702371, 32702373, 32702375, 32702377, 32702379, 32702381, 32702383, 32702385, 32702387, 32702389, 32702391, 32702393, 32702395, 32702397, + 32702399, 32702401, 32702403, 32702405, 32702407, 32702409, 32702411, 32702413, 32702415, 32702417, 32702419, 32702421, 32702423, 32702425, 32702427, + 32702429, 32702431, 32702433, 32702435, 32702437, 32702439, 32702441, 32702443, 32702445, 32702447, 32702449, 32702451, 32702453, 32702455, 32702457, + 32702459, 3121, 49, 0, 48, 3120, 32694279, 32694281, 32694283, 32694285, 32694287, 32694289, 32694291, 32694293, 32694295, + 32694297, 32694299, 32694301, 32694303, 32694305, 32694307, 32694309, 32694311, 32694313, 32694315, 32694317, 32694319, 32694321, 32694323, 32694325, + 32694327, 32694329, 32694331, 32694333, 32694335, 32694337, 32694339, 32694341, 32694343, 32694345, 32694347, 32694349, 32694351, 32694353, 32694355, + 32694357, 32694359, 32694361, 32694363, 32694365, 32694367, 32694369, 32694371, 32694373, 32694375, 32694377, 32694379, 32694381, 32694383, 32694385, + 32694387, 32694389, 32694391, 32694393, 32694395, 32694397, 32694399, 32718721, 32718723, 32718725, 32718727, 32718729, 32718731, 32718733, 32718735, + 32718737, 32718739, 32718741, 32718743, 32718745, 32718747, 32718749, 32718751, 32718753, 32718755, 32718757, 32718759, 32718761, 32718763, 32718765, + 32718767, 32718769, 32718771, 32718773, 32718775, 32718777, 32718779, 32718781, 32718783, 32718785, 32718787, 32718789, 32718791, 32718793, 32718795, + 32718797, 32718799, 32718801, 32718803, 32718805, 32718807, 32718809, 32718811, 32718813, 32718815, 32718817, 32718819, 32718821, 32718823, 32718825, + 32718827, 32718829, 32718831, 32718833, 32718835, 32718837, 32718839, 32718841, 32718843, 3119, 47, 0, 46, 3118, 32710663, + 32710665, 32710667, 32710669, 32710671, 32710673, 32710675, 32710677, 32710679, 32710681, 32710683, 32710685, 32710687, 32710689, 32710691, 32710693, + 32710695, 32710697, 32710699, 32710701, 32710703, 32710705, 32710707, 32710709, 32710711, 32710713, 32710715, 32710717, 32710719, 32710721, 32710723, + 32710725, 32710727, 32710729, 32710731, 32710733, 32710735, 32710737, 32710739, 32710741, 32710743, 32710745, 32710747, 32710749, 32710751, 32710753, + 32710755, 32710757, 32710759, 32710761, 32710763, 32710765, 32710767, 32710769, 32710771, 32710773, 32710775, 32710777, 32710779, 32710781, 32710783, + 32735105, 32735107, 32735109, 32735111, 32735113, 32735115, 32735117, 32735119, 32735121, 32735123, 32735125, 32735127, 32735129, 32735131, 32735133, + 32735135, 32735137, 32735139, 32735141, 32735143, 32735145, 32735147, 32735149, 32735151, 32735153, 32735155, 32735157, 32735159, 32735161, 32735163, + 32735165, 32735167, 32735169, 32735171, 32735173, 32735175, 32735177, 32735179, 32735181, 32735183, 32735185, 32735187, 32735189, 32735191, 32735193, + 32735195, 32735197, 32735199, 32735201, 32735203, 32735205, 32735207, 32735209, 32735211, 32735213, 32735215, 32735217, 32735219, 32735221, 32735223, + 32735225, 32735227, 3117, 45, 0, 44, 3116, 32727047, 32727049, 32727051, 32727053, 32727055, 32727057, 32727059, 32727061, + 32727063, 32727065, 32727067, 32727069, 32727071, 32727073, 32727075, 32727077, 32727079, 32727081, 32727083, 32727085, 32727087, 32727089, 32727091, + 32727093, 32727095, 32727097, 32727099, 32727101, 32727103, 32727105, 32727107, 32727109, 32727111, 32727113, 32727115, 32727117, 32727119, 32727121, + 32727123, 32727125, 32727127, 32727129, 32727131, 32727133, 32727135, 32727137, 32727139, 32727141, 32727143, 32727145, 32727147, 32727149, 32727151, + 32727153, 32727155, 32727157, 32727159, 32727161, 32727163, 32727165, 32727167, 32751489, 32751491, 32751493, 32751495, 32751497, 32751499, 32751501, + 32751503, 32751505, 32751507, 32751509, 32751511, 32751513, 32751515, 32751517, 32751519, 32751521, 32751523, 32751525, 32751527, 32751529, 32751531, + 32751533, 32751535, 32751537, 32751539, 32751541, 32751543, 32751545, 32751547, 32751549, 32751551, 32751553, 32751555, 32751557, 32751559, 32751561, + 32751563, 32751565, 32751567, 32751569, 32751571, 32751573, 32751575, 32751577, 32751579, 32751581, 32751583, 32751585, 32751587, 32751589, 32751591, + 32751593, 32751595, 32751597, 32751599, 32751601, 32751603, 32751605, 32751607, 32751609, 32751611, 3115, 43, 0, 42, 3114, + 32743431, 32743433, 32743435, 32743437, 32743439, 32743441, 32743443, 32743445, 32743447, 32743449, 32743451, 32743453, 32743455, 32743457, 32743459, + 32743461, 32743463, 32743465, 32743467, 32743469, 32743471, 32743473, 32743475, 32743477, 32743479, 32743481, 32743483, 32743485, 32743487, 32743489, + 32743491, 32743493, 32743495, 32743497, 32743499, 32743501, 32743503, 32743505, 32743507, 32743509, 32743511, 32743513, 32743515, 32743517, 32743519, + 32743521, 32743523, 32743525, 32743527, 32743529, 32743531, 32743533, 32743535, 32743537, 32743539, 32743541, 32743543, 32743545, 32743547, 32743549, + 32743551, 32767873, 32767875, 32767877, 32767879, 32767881, 32767883, 32767885, 32767887, 32767889, 32767891, 32767893, 32767895, 32767897, 32767899, + 32767901, 32767903, 32767905, 32767907, 32767909, 32767911, 32767913, 32767915, 32767917, 32767919, 32767921, 32767923, 32767925, 32767927, 32767929, + 32767931, 32767933, 32767935, 32767937, 32767939, 32767941, 32767943, 32767945, 32767947, 32767949, 32767951, 32767953, 32767955, 32767957, 32767959, + 32767961, 32767963, 32767965, 32767967, 32767969, 32767971, 32767973, 32767975, 32767977, 32767979, 32767981, 32767983, 32767985, 32767987, 32767989, + 32767991, 32767993, 32767995, 3113, 41, 0, 40, 3112, 32759815, 32759817, 32759819, 32759821, 32759823, 32759825, 32759827, + 32759829, 32759831, 32759833, 32759835, 32759837, 32759839, 32759841, 32759843, 32759845, 32759847, 32759849, 32759851, 32759853, 32759855, 32759857, + 32759859, 32759861, 32759863, 32759865, 32759867, 32759869, 32759871, 32759873, 32759875, 32759877, 32759879, 32759881, 32759883, 32759885, 32759887, + 32759889, 32759891, 32759893, 32759895, 32759897, 32759899, 32759901, 32759903, 32759905, 32759907, 32759909, 32759911, 32759913, 32759915, 32759917, + 32759919, 32759921, 32759923, 32759925, 32759927, 32759929, 32759931, 32759933, 32759935, 32784257, 32784259, 32784261, 32784263, 32784265, 32784267, + 32784269, 32784271, 32784273, 32784275, 32784277, 32784279, 32784281, 32784283, 32784285, 32784287, 32784289, 32784291, 32784293, 32784295, 32784297, + 32784299, 32784301, 32784303, 32784305, 32784307, 32784309, 32784311, 32784313, 32784315, 32784317, 32784319, 32784321, 32784323, 32784325, 32784327, + 32784329, 32784331, 32784333, 32784335, 32784337, 32784339, 32784341, 32784343, 32784345, 32784347, 32784349, 32784351, 32784353, 32784355, 32784357, + 32784359, 32784361, 32784363, 32784365, 32784367, 32784369, 32784371, 32784373, 32784375, 32784377, 32784379, 3111, 39, 0, 38, + 3110, 32776199, 32776201, 32776203, 32776205, 32776207, 32776209, 32776211, 32776213, 32776215, 32776217, 32776219, 32776221, 32776223, 32776225, + 32776227, 32776229, 32776231, 32776233, 32776235, 32776237, 32776239, 32776241, 32776243, 32776245, 32776247, 32776249, 32776251, 32776253, 32776255, + 32776257, 32776259, 32776261, 32776263, 32776265, 32776267, 32776269, 32776271, 32776273, 32776275, 32776277, 32776279, 32776281, 32776283, 32776285, + 32776287, 32776289, 32776291, 32776293, 32776295, 32776297, 32776299, 32776301, 32776303, 32776305, 32776307, 32776309, 32776311, 32776313, 32776315, + 32776317, 32776319, 32800641, 32800643, 32800645, 32800647, 32800649, 32800651, 32800653, 32800655, 32800657, 32800659, 32800661, 32800663, 32800665, + 32800667, 32800669, 32800671, 32800673, 32800675, 32800677, 32800679, 32800681, 32800683, 32800685, 32800687, 32800689, 32800691, 32800693, 32800695, + 32800697, 32800699, 32800701, 32800703, 32800705, 32800707, 32800709, 32800711, 32800713, 32800715, 32800717, 32800719, 32800721, 32800723, 32800725, + 32800727, 32800729, 32800731, 32800733, 32800735, 32800737, 32800739, 32800741, 32800743, 32800745, 32800747, 32800749, 32800751, 32800753, 32800755, + 32800757, 32800759, 32800761, 32800763, 6193, 49, 0, 48, 6192, 32792583, 32792585, 32792587, 32792589, 32792591, 32792593, + 32792595, 32792597, 32792599, 32792601, 32792603, 32792605, 32792607, 32792609, 32792611, 32792613, 32792615, 32792617, 32792619, 32792621, 32792623, + 32792625, 32792627, 32792629, 32792631, 32792633, 32792635, 32792637, 32792639, 32792641, 32792643, 32792645, 32792647, 32792649, 32792651, 32792653, + 32792655, 32792657, 32792659, 32792661, 32792663, 32792665, 32792667, 32792669, 32792671, 32792673, 32792675, 32792677, 32792679, 32792681, 32792683, + 32792685, 32792687, 32792689, 32792691, 32792693, 32792695, 32792697, 32792699, 32792701, 32792703, 32817025, 32817027, 32817029, 32817031, 32817033, + 32817035, 32817037, 32817039, 32817041, 32817043, 32817045, 32817047, 32817049, 32817051, 32817053, 32817055, 32817057, 32817059, 32817061, 32817063, + 32817065, 32817067, 32817069, 32817071, 32817073, 32817075, 32817077, 32817079, 32817081, 32817083, 32817085, 32817087, 32817089, 32817091, 32817093, + 32817095, 32817097, 32817099, 32817101, 32817103, 32817105, 32817107, 32817109, 32817111, 32817113, 32817115, 32817117, 32817119, 32817121, 32817123, + 32817125, 32817127, 32817129, 32817131, 32817133, 32817135, 32817137, 32817139, 32817141, 32817143, 32817145, 32817147, 6191, 47, 0, + 46, 6190, 32808967, 32808969, 32808971, 32808973, 32808975, 32808977, 32808979, 32808981, 32808983, 32808985, 32808987, 32808989, 32808991, + 32808993, 32808995, 32808997, 32808999, 32809001, 32809003, 32809005, 32809007, 32809009, 32809011, 32809013, 32809015, 32809017, 32809019, 32809021, + 32809023, 32809025, 32809027, 32809029, 32809031, 32809033, 32809035, 32809037, 32809039, 32809041, 32809043, 32809045, 32809047, 32809049, 32809051, + 32809053, 32809055, 32809057, 32809059, 32809061, 32809063, 32809065, 32809067, 32809069, 32809071, 32809073, 32809075, 32809077, 32809079, 32809081, + 32809083, 32809085, 32809087, 32833409, 32833411, 32833413, 32833415, 32833417, 32833419, 32833421, 32833423, 32833425, 32833427, 32833429, 32833431, + 32833433, 32833435, 32833437, 32833439, 32833441, 32833443, 32833445, 32833447, 32833449, 32833451, 32833453, 32833455, 32833457, 32833459, 32833461, + 32833463, 32833465, 32833467, 32833469, 32833471, 32833473, 32833475, 32833477, 32833479, 32833481, 32833483, 32833485, 32833487, 32833489, 32833491, + 32833493, 32833495, 32833497, 32833499, 32833501, 32833503, 32833505, 32833507, 32833509, 32833511, 32833513, 32833515, 32833517, 32833519, 32833521, + 32833523, 32833525, 32833527, 32833529, 32833531, 6189, 45, 0, 44, 6188, 32825351, 32825353, 32825355, 32825357, 32825359, + 32825361, 32825363, 32825365, 32825367, 32825369, 32825371, 32825373, 32825375, 32825377, 32825379, 32825381, 32825383, 32825385, 32825387, 32825389, + 32825391, 32825393, 32825395, 32825397, 32825399, 32825401, 32825403, 32825405, 32825407, 32825409, 32825411, 32825413, 32825415, 32825417, 32825419, + 32825421, 32825423, 32825425, 32825427, 32825429, 32825431, 32825433, 32825435, 32825437, 32825439, 32825441, 32825443, 32825445, 32825447, 32825449, + 32825451, 32825453, 32825455, 32825457, 32825459, 32825461, 32825463, 32825465, 32825467, 32825469, 32825471, 32849793, 32849795, 32849797, 32849799, + 32849801, 32849803, 32849805, 32849807, 32849809, 32849811, 32849813, 32849815, 32849817, 32849819, 32849821, 32849823, 32849825, 32849827, 32849829, + 32849831, 32849833, 32849835, 32849837, 32849839, 32849841, 32849843, 32849845, 32849847, 32849849, 32849851, 32849853, 32849855, 32849857, 32849859, + 32849861, 32849863, 32849865, 32849867, 32849869, 32849871, 32849873, 32849875, 32849877, 32849879, 32849881, 32849883, 32849885, 32849887, 32849889, + 32849891, 32849893, 32849895, 32849897, 32849899, 32849901, 32849903, 32849905, 32849907, 32849909, 32849911, 32849913, 32849915, 6187, 43, + 0, 42, 6186, 32841735, 32841737, 32841739, 32841741, 32841743, 32841745, 32841747, 32841749, 32841751, 32841753, 32841755, 32841757, + 32841759, 32841761, 32841763, 32841765, 32841767, 32841769, 32841771, 32841773, 32841775, 32841777, 32841779, 32841781, 32841783, 32841785, 32841787, + 32841789, 32841791, 32841793, 32841795, 32841797, 32841799, 32841801, 32841803, 32841805, 32841807, 32841809, 32841811, 32841813, 32841815, 32841817, + 32841819, 32841821, 32841823, 32841825, 32841827, 32841829, 32841831, 32841833, 32841835, 32841837, 32841839, 32841841, 32841843, 32841845, 32841847, + 32841849, 32841851, 32841853, 32841855, 32866177, 32866179, 32866181, 32866183, 32866185, 32866187, 32866189, 32866191, 32866193, 32866195, 32866197, + 32866199, 32866201, 32866203, 32866205, 32866207, 32866209, 32866211, 32866213, 32866215, 32866217, 32866219, 32866221, 32866223, 32866225, 32866227, + 32866229, 32866231, 32866233, 32866235, 32866237, 32866239, 32866241, 32866243, 32866245, 32866247, 32866249, 32866251, 32866253, 32866255, 32866257, + 32866259, 32866261, 32866263, 32866265, 32866267, 32866269, 32866271, 32866273, 32866275, 32866277, 32866279, 32866281, 32866283, 32866285, 32866287, + 32866289, 32866291, 32866293, 32866295, 32866297, 32866299, 6185, 41, 0, 40, 6184, 32858119, 32858121, 32858123, 32858125, + 32858127, 32858129, 32858131, 32858133, 32858135, 32858137, 32858139, 32858141, 32858143, 32858145, 32858147, 32858149, 32858151, 32858153, 32858155, + 32858157, 32858159, 32858161, 32858163, 32858165, 32858167, 32858169, 32858171, 32858173, 32858175, 32858177, 32858179, 32858181, 32858183, 32858185, + 32858187, 32858189, 32858191, 32858193, 32858195, 32858197, 32858199, 32858201, 32858203, 32858205, 32858207, 32858209, 32858211, 32858213, 32858215, + 32858217, 32858219, 32858221, 32858223, 32858225, 32858227, 32858229, 32858231, 32858233, 32858235, 32858237, 32858239, 32882561, 32882563, 32882565, + 32882567, 32882569, 32882571, 32882573, 32882575, 32882577, 32882579, 32882581, 32882583, 32882585, 32882587, 32882589, 32882591, 32882593, 32882595, + 32882597, 32882599, 32882601, 32882603, 32882605, 32882607, 32882609, 32882611, 32882613, 32882615, 32882617, 32882619, 32882621, 32882623, 32882625, + 32882627, 32882629, 32882631, 32882633, 32882635, 32882637, 32882639, 32882641, 32882643, 32882645, 32882647, 32882649, 32882651, 32882653, 32882655, + 32882657, 32882659, 32882661, 32882663, 32882665, 32882667, 32882669, 32882671, 32882673, 32882675, 32882677, 32882679, 32882681, 32882683, 6183, + 39, 0, 38, 6182, 32874503, 32874505, 32874507, 32874509, 32874511, 32874513, 32874515, 32874517, 32874519, 32874521, 32874523, + 32874525, 32874527, 32874529, 32874531, 32874533, 32874535, 32874537, 32874539, 32874541, 32874543, 32874545, 32874547, 32874549, 32874551, 32874553, + 32874555, 32874557, 32874559, 32874561, 32874563, 32874565, 32874567, 32874569, 32874571, 32874573, 32874575, 32874577, 32874579, 32874581, 32874583, + 32874585, 32874587, 32874589, 32874591, 32874593, 32874595, 32874597, 32874599, 32874601, 32874603, 32874605, 32874607, 32874609, 32874611, 32874613, + 32874615, 32874617, 32874619, 32874621, 32874623, 32898945, 32898947, 32898949, 32898951, 32898953, 32898955, 32898957, 32898959, 32898961, 32898963, + 32898965, 32898967, 32898969, 32898971, 32898973, 32898975, 32898977, 32898979, 32898981, 32898983, 32898985, 32898987, 32898989, 32898991, 32898993, + 32898995, 32898997, 32898999, 32899001, 32899003, 32899005, 32899007, 32899009, 32899011, 32899013, 32899015, 32899017, 32899019, 32899021, 32899023, + 32899025, 32899027, 32899029, 32899031, 32899033, 32899035, 32899037, 32899039, 32899041, 32899043, 32899045, 32899047, 32899049, 32899051, 32899053, + 32899055, 32899057, 32899059, 32899061, 32899063, 32899065, 32899067, 6181, 37, 0, 36, 6180, 32890887, 32890889, 32890891, + 32890893, 32890895, 32890897, 32890899, 32890901, 32890903, 32890905, 32890907, 32890909, 32890911, 32890913, 32890915, 32890917, 32890919, 32890921, + 32890923, 32890925, 32890927, 32890929, 32890931, 32890933, 32890935, 32890937, 32890939, 32890941, 32890943, 32890945, 32890947, 32890949, 32890951, + 32890953, 32890955, 32890957, 32890959, 32890961, 32890963, 32890965, 32890967, 32890969, 32890971, 32890973, 32890975, 32890977, 32890979, 32890981, + 32890983, 32890985, 32890987, 32890989, 32890991, 32890993, 32890995, 32890997, 32890999, 32891001, 32891003, 32891005, 32891007, 32915329, 32915331, + 32915333, 32915335, 32915337, 32915339, 32915341, 32915343, 32915345, 32915347, 32915349, 32915351, 32915353, 32915355, 32915357, 32915359, 32915361, + 32915363, 32915365, 32915367, 32915369, 32915371, 32915373, 32915375, 32915377, 32915379, 32915381, 32915383, 32915385, 32915387, 32915389, 32915391, + 32915393, 32915395, 32915397, 32915399, 32915401, 32915403, 32915405, 32915407, 32915409, 32915411, 32915413, 32915415, 32915417, 32915419, 32915421, + 32915423, 32915425, 32915427, 32915429, 32915431, 32915433, 32915435, 32915437, 32915439, 32915441, 32915443, 32915445, 32915447, 32915449, 32915451, + 6179, 35, 0, 34, 6178, 32907271, 32907273, 32907275, 32907277, 32907279, 32907281, 32907283, 32907285, 32907287, 32907289, + 32907291, 32907293, 32907295, 32907297, 32907299, 32907301, 32907303, 32907305, 32907307, 32907309, 32907311, 32907313, 32907315, 32907317, 32907319, + 32907321, 32907323, 32907325, 32907327, 32907329, 32907331, 32907333, 32907335, 32907337, 32907339, 32907341, 32907343, 32907345, 32907347, 32907349, + 32907351, 32907353, 32907355, 32907357, 32907359, 32907361, 32907363, 32907365, 32907367, 32907369, 32907371, 32907373, 32907375, 32907377, 32907379, + 32907381, 32907383, 32907385, 32907387, 32907389, 32907391, 32931713, 32931715, 32931717, 32931719, 32931721, 32931723, 32931725, 32931727, 32931729, + 32931731, 32931733, 32931735, 32931737, 32931739, 32931741, 32931743, 32931745, 32931747, 32931749, 32931751, 32931753, 32931755, 32931757, 32931759, + 32931761, 32931763, 32931765, 32931767, 32931769, 32931771, 32931773, 32931775, 32931777, 32931779, 32931781, 32931783, 32931785, 32931787, 32931789, + 32931791, 32931793, 32931795, 32931797, 32931799, 32931801, 32931803, 32931805, 32931807, 32931809, 32931811, 32931813, 32931815, 32931817, 32931819, + 32931821, 32931823, 32931825, 32931827, 32931829, 32931831, 32931833, 32931835, 12303, 15, 0, 14, 12302, 32923655, 32923657, + 32923659, 32923661, 32923663, 32923665, 32923667, 32923669, 32923671, 32923673, 32923675, 32923677, 32923679, 32923681, 32923683, 32923685, 32923687, + 32923689, 32923691, 32923693, 32923695, 32923697, 32923699, 32923701, 32923703, 32923705, 32923707, 32923709, 32923711, 32923713, 32923715, 32923717, + 32923719, 32923721, 32923723, 32923725, 32923727, 32923729, 32923731, 32923733, 32923735, 32923737, 32923739, 32923741, 32923743, 32923745, 32923747, + 32923749, 32923751, 32923753, 32923755, 32923757, 32923759, 32923761, 32923763, 32923765, 32923767, 32923769, 32923771, 32923773, 32923775, 32948097, + 32948099, 32948101, 32948103, 32948105, 32948107, 32948109, 32948111, 32948113, 32948115, 32948117, 32948119, 32948121, 32948123, 32948125, 32948127, + 32948129, 32948131, 32948133, 32948135, 32948137, 32948139, 32948141, 32948143, 32948145, 32948147, 32948149, 32948151, 32948153, 32948155, 32948157, + 32948159, 32948161, 32948163, 32948165, 32948167, 32948169, 32948171, 32948173, 32948175, 32948177, 32948179, 32948181, 32948183, 32948185, 32948187, + 32948189, 32948191, 32948193, 32948195, 32948197, 32948199, 32948201, 32948203, 32948205, 32948207, 32948209, 32948211, 32948213, 32948215, 32948217, + 32948219, 12301, 13, 0, 12, 12300, 32940039, 32940041, 32940043, 32940045, 32940047, 32940049, 32940051, 32940053, 32940055, + 32940057, 32940059, 32940061, 32940063, 32940065, 32940067, 32940069, 32940071, 32940073, 32940075, 32940077, 32940079, 32940081, 32940083, 32940085, + 32940087, 32940089, 32940091, 32940093, 32940095, 32940097, 32940099, 32940101, 32940103, 32940105, 32940107, 32940109, 32940111, 32940113, 32940115, + 32940117, 32940119, 32940121, 32940123, 32940125, 32940127, 32940129, 32940131, 32940133, 32940135, 32940137, 32940139, 32940141, 32940143, 32940145, + 32940147, 32940149, 32940151, 32940153, 32940155, 32940157, 32940159, 32964481, 32964483, 32964485, 32964487, 32964489, 32964491, 32964493, 32964495, + 32964497, 32964499, 32964501, 32964503, 32964505, 32964507, 32964509, 32964511, 32964513, 32964515, 32964517, 32964519, 32964521, 32964523, 32964525, + 32964527, 32964529, 32964531, 32964533, 32964535, 32964537, 32964539, 32964541, 32964543, 32964545, 32964547, 32964549, 32964551, 32964553, 32964555, + 32964557, 32964559, 32964561, 32964563, 32964565, 32964567, 32964569, 32964571, 32964573, 32964575, 32964577, 32964579, 32964581, 32964583, 32964585, + 32964587, 32964589, 32964591, 32964593, 32964595, 32964597, 32964599, 32964601, 32964603, 12299, 11, 0, 10, 12298, 32956423, + 32956425, 32956427, 32956429, 32956431, 32956433, 32956435, 32956437, 32956439, 32956441, 32956443, 32956445, 32956447, 32956449, 32956451, 32956453, + 32956455, 32956457, 32956459, 32956461, 32956463, 32956465, 32956467, 32956469, 32956471, 32956473, 32956475, 32956477, 32956479, 32956481, 32956483, + 32956485, 32956487, 32956489, 32956491, 32956493, 32956495, 32956497, 32956499, 32956501, 32956503, 32956505, 32956507, 32956509, 32956511, 32956513, + 32956515, 32956517, 32956519, 32956521, 32956523, 32956525, 32956527, 32956529, 32956531, 32956533, 32956535, 32956537, 32956539, 32956541, 32956543, + 32980865, 32980867, 32980869, 32980871, 32980873, 32980875, 32980877, 32980879, 32980881, 32980883, 32980885, 32980887, 32980889, 32980891, 32980893, + 32980895, 32980897, 32980899, 32980901, 32980903, 32980905, 32980907, 32980909, 32980911, 32980913, 32980915, 32980917, 32980919, 32980921, 32980923, + 32980925, 32980927, 32980929, 32980931, 32980933, 32980935, 32980937, 32980939, 32980941, 32980943, 32980945, 32980947, 32980949, 32980951, 32980953, + 32980955, 32980957, 32980959, 32980961, 32980963, 32980965, 32980967, 32980969, 32980971, 32980973, 32980975, 32980977, 32980979, 32980981, 32980983, + 32980985, 32980987, 12297, 9, 0, 8, 12296, 32972807, 32972809, 32972811, 32972813, 32972815, 32972817, 32972819, 32972821, + 32972823, 32972825, 32972827, 32972829, 32972831, 32972833, 32972835, 32972837, 32972839, 32972841, 32972843, 32972845, 32972847, 32972849, 32972851, + 32972853, 32972855, 32972857, 32972859, 32972861, 32972863, 32972865, 32972867, 32972869, 32972871, 32972873, 32972875, 32972877, 32972879, 32972881, + 32972883, 32972885, 32972887, 32972889, 32972891, 32972893, 32972895, 32972897, 32972899, 32972901, 32972903, 32972905, 32972907, 32972909, 32972911, + 32972913, 32972915, 32972917, 32972919, 32972921, 32972923, 32972925, 32972927, 32997249, 32997251, 32997253, 32997255, 32997257, 32997259, 32997261, + 32997263, 32997265, 32997267, 32997269, 32997271, 32997273, 32997275, 32997277, 32997279, 32997281, 32997283, 32997285, 32997287, 32997289, 32997291, + 32997293, 32997295, 32997297, 32997299, 32997301, 32997303, 32997305, 32997307, 32997309, 32997311, 32997313, 32997315, 32997317, 32997319, 32997321, + 32997323, 32997325, 32997327, 32997329, 32997331, 32997333, 32997335, 32997337, 32997339, 32997341, 32997343, 32997345, 32997347, 32997349, 32997351, + 32997353, 32997355, 32997357, 32997359, 32997361, 32997363, 32997365, 32997367, 32997369, 32997371, 24649, 73, 0, 72, 24648, + 32989191, 32989193, 32989195, 32989197, 32989199, 32989201, 32989203, 32989205, 32989207, 32989209, 32989211, 32989213, 32989215, 32989217, 32989219, + 32989221, 32989223, 32989225, 32989227, 32989229, 32989231, 32989233, 32989235, 32989237, 32989239, 32989241, 32989243, 32989245, 32989247, 32989249, + 32989251, 32989253, 32989255, 32989257, 32989259, 32989261, 32989263, 32989265, 32989267, 32989269, 32989271, 32989273, 32989275, 32989277, 32989279, + 32989281, 32989283, 32989285, 32989287, 32989289, 32989291, 32989293, 32989295, 32989297, 32989299, 32989301, 32989303, 32989305, 32989307, 32989309, + 32989311, 33013633, 33013635, 33013637, 33013639, 33013641, 33013643, 33013645, 33013647, 33013649, 33013651, 33013653, 33013655, 33013657, 33013659, + 33013661, 33013663, 33013665, 33013667, 33013669, 33013671, 33013673, 33013675, 33013677, 33013679, 33013681, 33013683, 33013685, 33013687, 33013689, + 33013691, 33013693, 33013695, 33013697, 33013699, 33013701, 33013703, 33013705, 33013707, 33013709, 33013711, 33013713, 33013715, 33013717, 33013719, + 33013721, 33013723, 33013725, 33013727, 33013729, 33013731, 33013733, 33013735, 33013737, 33013739, 33013741, 33013743, 33013745, 33013747, 33013749, + 33013751, 33013753, 33013755, 24651, 75, 0, 74, 24650, 33005575, 33005577, 33005579, 33005581, 33005583, 33005585, 33005587, + 33005589, 33005591, 33005593, 33005595, 33005597, 33005599, 33005601, 33005603, 33005605, 33005607, 33005609, 33005611, 33005613, 33005615, 33005617, + 33005619, 33005621, 33005623, 33005625, 33005627, 33005629, 33005631, 33005633, 33005635, 33005637, 33005639, 33005641, 33005643, 33005645, 33005647, + 33005649, 33005651, 33005653, 33005655, 33005657, 33005659, 33005661, 33005663, 33005665, 33005667, 33005669, 33005671, 33005673, 33005675, 33005677, + 33005679, 33005681, 33005683, 33005685, 33005687, 33005689, 33005691, 33005693, 33005695, 33030017, 33030019, 33030021, 33030023, 33030025, 33030027, + 33030029, 33030031, 33030033, 33030035, 33030037, 33030039, 33030041, 33030043, 33030045, 33030047, 33030049, 33030051, 33030053, 33030055, 33030057, + 33030059, 33030061, 33030063, 33030065, 33030067, 33030069, 33030071, 33030073, 33030075, 33030077, 33030079, 33030081, 33030083, 33030085, 33030087, + 33030089, 33030091, 33030093, 33030095, 33030097, 33030099, 33030101, 33030103, 33030105, 33030107, 33030109, 33030111, 33030113, 33030115, 33030117, + 33030119, 33030121, 33030123, 33030125, 33030127, 33030129, 33030131, 33030133, 33030135, 33030137, 33030139, 24653, 77, 0, 76, + 24652, 33021959, 33021961, 33021963, 33021965, 33021967, 33021969, 33021971, 33021973, 33021975, 33021977, 33021979, 33021981, 33021983, 33021985, + 33021987, 33021989, 33021991, 33021993, 33021995, 33021997, 33021999, 33022001, 33022003, 33022005, 33022007, 33022009, 33022011, 33022013, 33022015, + 33022017, 33022019, 33022021, 33022023, 33022025, 33022027, 33022029, 33022031, 33022033, 33022035, 33022037, 33022039, 33022041, 33022043, 33022045, + 33022047, 33022049, 33022051, 33022053, 33022055, 33022057, 33022059, 33022061, 33022063, 33022065, 33022067, 33022069, 33022071, 33022073, 33022075, + 33022077, 33022079, 33046401, 33046403, 33046405, 33046407, 33046409, 33046411, 33046413, 33046415, 33046417, 33046419, 33046421, 33046423, 33046425, + 33046427, 33046429, 33046431, 33046433, 33046435, 33046437, 33046439, 33046441, 33046443, 33046445, 33046447, 33046449, 33046451, 33046453, 33046455, + 33046457, 33046459, 33046461, 33046463, 33046465, 33046467, 33046469, 33046471, 33046473, 33046475, 33046477, 33046479, 33046481, 33046483, 33046485, + 33046487, 33046489, 33046491, 33046493, 33046495, 33046497, 33046499, 33046501, 33046503, 33046505, 33046507, 33046509, 33046511, 33046513, 33046515, + 33046517, 33046519, 33046521, 33046523, 24655, 79, 0, 78, 24654, 33038343, 33038345, 33038347, 33038349, 33038351, 33038353, + 33038355, 33038357, 33038359, 33038361, 33038363, 33038365, 33038367, 33038369, 33038371, 33038373, 33038375, 33038377, 33038379, 33038381, 33038383, + 33038385, 33038387, 33038389, 33038391, 33038393, 33038395, 33038397, 33038399, 33038401, 33038403, 33038405, 33038407, 33038409, 33038411, 33038413, + 33038415, 33038417, 33038419, 33038421, 33038423, 33038425, 33038427, 33038429, 33038431, 33038433, 33038435, 33038437, 33038439, 33038441, 33038443, + 33038445, 33038447, 33038449, 33038451, 33038453, 33038455, 33038457, 33038459, 33038461, 33038463, 33062785, 33062787, 33062789, 33062791, 33062793, + 33062795, 33062797, 33062799, 33062801, 33062803, 33062805, 33062807, 33062809, 33062811, 33062813, 33062815, 33062817, 33062819, 33062821, 33062823, + 33062825, 33062827, 33062829, 33062831, 33062833, 33062835, 33062837, 33062839, 33062841, 33062843, 33062845, 33062847, 33062849, 33062851, 33062853, + 33062855, 33062857, 33062859, 33062861, 33062863, 33062865, 33062867, 33062869, 33062871, 33062873, 33062875, 33062877, 33062879, 33062881, 33062883, + 33062885, 33062887, 33062889, 33062891, 33062893, 33062895, 33062897, 33062899, 33062901, 33062903, 33062905, 33062907, 49329, 177, 0, + 176, 49328, 33054727, 33054729, 33054731, 33054733, 33054735, 33054737, 33054739, 33054741, 33054743, 33054745, 33054747, 33054749, 33054751, + 33054753, 33054755, 33054757, 33054759, 33054761, 33054763, 33054765, 33054767, 33054769, 33054771, 33054773, 33054775, 33054777, 33054779, 33054781, + 33054783, 33054785, 33054787, 33054789, 33054791, 33054793, 33054795, 33054797, 33054799, 33054801, 33054803, 33054805, 33054807, 33054809, 33054811, + 33054813, 33054815, 33054817, 33054819, 33054821, 33054823, 33054825, 33054827, 33054829, 33054831, 33054833, 33054835, 33054837, 33054839, 33054841, + 33054843, 33054845, 33054847, 33079169, 33079171, 33079173, 33079175, 33079177, 33079179, 33079181, 33079183, 33079185, 33079187, 33079189, 33079191, + 33079193, 33079195, 33079197, 33079199, 33079201, 33079203, 33079205, 33079207, 33079209, 33079211, 33079213, 33079215, 33079217, 33079219, 33079221, + 33079223, 33079225, 33079227, 33079229, 33079231, 33079233, 33079235, 33079237, 33079239, 33079241, 33079243, 33079245, 33079247, 33079249, 33079251, + 33079253, 33079255, 33079257, 33079259, 33079261, 33079263, 33079265, 33079267, 33079269, 33079271, 33079273, 33079275, 33079277, 33079279, 33079281, + 33079283, 33079285, 33079287, 33079289, 33079291, 49331, 179, 0, 178, 49330, 33071111, 33071113, 33071115, 33071117, 33071119, + 33071121, 33071123, 33071125, 33071127, 33071129, 33071131, 33071133, 33071135, 33071137, 33071139, 33071141, 33071143, 33071145, 33071147, 33071149, + 33071151, 33071153, 33071155, 33071157, 33071159, 33071161, 33071163, 33071165, 33071167, 33071169, 33071171, 33071173, 33071175, 33071177, 33071179, + 33071181, 33071183, 33071185, 33071187, 33071189, 33071191, 33071193, 33071195, 33071197, 33071199, 33071201, 33071203, 33071205, 33071207, 33071209, + 33071211, 33071213, 33071215, 33071217, 33071219, 33071221, 33071223, 33071225, 33071227, 33071229, 33071231, 33095553, 33095555, 33095557, 33095559, + 33095561, 33095563, 33095565, 33095567, 33095569, 33095571, 33095573, 33095575, 33095577, 33095579, 33095581, 33095583, 33095585, 33095587, 33095589, + 33095591, 33095593, 33095595, 33095597, 33095599, 33095601, 33095603, 33095605, 33095607, 33095609, 33095611, 33095613, 33095615, 33095617, 33095619, + 33095621, 33095623, 33095625, 33095627, 33095629, 33095631, 33095633, 33095635, 33095637, 33095639, 33095641, 33095643, 33095645, 33095647, 33095649, + 33095651, 33095653, 33095655, 33095657, 33095659, 33095661, 33095663, 33095665, 33095667, 33095669, 33095671, 33095673, 33095675, 49333, 181, + 0, 180, 49332, 33087495, 33087497, 33087499, 33087501, 33087503, 33087505, 33087507, 33087509, 33087511, 33087513, 33087515, 33087517, + 33087519, 33087521, 33087523, 33087525, 33087527, 33087529, 33087531, 33087533, 33087535, 33087537, 33087539, 33087541, 33087543, 33087545, 33087547, + 33087549, 33087551, 33087553, 33087555, 33087557, 33087559, 33087561, 33087563, 33087565, 33087567, 33087569, 33087571, 33087573, 33087575, 33087577, + 33087579, 33087581, 33087583, 33087585, 33087587, 33087589, 33087591, 33087593, 33087595, 33087597, 33087599, 33087601, 33087603, 33087605, 33087607, + 33087609, 33087611, 33087613, 33087615, 33111937, 33111939, 33111941, 33111943, 33111945, 33111947, 33111949, 33111951, 33111953, 33111955, 33111957, + 33111959, 33111961, 33111963, 33111965, 33111967, 33111969, 33111971, 33111973, 33111975, 33111977, 33111979, 33111981, 33111983, 33111985, 33111987, + 33111989, 33111991, 33111993, 33111995, 33111997, 33111999, 33112001, 33112003, 33112005, 33112007, 33112009, 33112011, 33112013, 33112015, 33112017, + 33112019, 33112021, 33112023, 33112025, 33112027, 33112029, 33112031, 33112033, 33112035, 33112037, 33112039, 33112041, 33112043, 33112045, 33112047, + 33112049, 33112051, 33112053, 33112055, 33112057, 33112059, 49335, 183, 0, 182, 49334, 33103879, 33103881, 33103883, 33103885, + 33103887, 33103889, 33103891, 33103893, 33103895, 33103897, 33103899, 33103901, 33103903, 33103905, 33103907, 33103909, 33103911, 33103913, 33103915, + 33103917, 33103919, 33103921, 33103923, 33103925, 33103927, 33103929, 33103931, 33103933, 33103935, 33103937, 33103939, 33103941, 33103943, 33103945, + 33103947, 33103949, 33103951, 33103953, 33103955, 33103957, 33103959, 33103961, 33103963, 33103965, 33103967, 33103969, 33103971, 33103973, 33103975, + 33103977, 33103979, 33103981, 33103983, 33103985, 33103987, 33103989, 33103991, 33103993, 33103995, 33103997, 33103999, 33128321, 33128323, 33128325, + 33128327, 33128329, 33128331, 33128333, 33128335, 33128337, 33128339, 33128341, 33128343, 33128345, 33128347, 33128349, 33128351, 33128353, 33128355, + 33128357, 33128359, 33128361, 33128363, 33128365, 33128367, 33128369, 33128371, 33128373, 33128375, 33128377, 33128379, 33128381, 33128383, 33128385, + 33128387, 33128389, 33128391, 33128393, 33128395, 33128397, 33128399, 33128401, 33128403, 33128405, 33128407, 33128409, 33128411, 33128413, 33128415, + 33128417, 33128419, 33128421, 33128423, 33128425, 33128427, 33128429, 33128431, 33128433, 33128435, 33128437, 33128439, 33128441, 33128443, 49337, + 185, 0, 184, 49336, 33120263, 33120265, 33120267, 33120269, 33120271, 33120273, 33120275, 33120277, 33120279, 33120281, 33120283, + 33120285, 33120287, 33120289, 33120291, 33120293, 33120295, 33120297, 33120299, 33120301, 33120303, 33120305, 33120307, 33120309, 33120311, 33120313, + 33120315, 33120317, 33120319, 33120321, 33120323, 33120325, 33120327, 33120329, 33120331, 33120333, 33120335, 33120337, 33120339, 33120341, 33120343, + 33120345, 33120347, 33120349, 33120351, 33120353, 33120355, 33120357, 33120359, 33120361, 33120363, 33120365, 33120367, 33120369, 33120371, 33120373, + 33120375, 33120377, 33120379, 33120381, 33120383, 33144705, 33144707, 33144709, 33144711, 33144713, 33144715, 33144717, 33144719, 33144721, 33144723, + 33144725, 33144727, 33144729, 33144731, 33144733, 33144735, 33144737, 33144739, 33144741, 33144743, 33144745, 33144747, 33144749, 33144751, 33144753, + 33144755, 33144757, 33144759, 33144761, 33144763, 33144765, 33144767, 33144769, 33144771, 33144773, 33144775, 33144777, 33144779, 33144781, 33144783, + 33144785, 33144787, 33144789, 33144791, 33144793, 33144795, 33144797, 33144799, 33144801, 33144803, 33144805, 33144807, 33144809, 33144811, 33144813, + 33144815, 33144817, 33144819, 33144821, 33144823, 33144825, 33144827, 49339, 187, 0, 186, 49338, 33136647, 33136649, 33136651, + 33136653, 33136655, 33136657, 33136659, 33136661, 33136663, 33136665, 33136667, 33136669, 33136671, 33136673, 33136675, 33136677, 33136679, 33136681, + 33136683, 33136685, 33136687, 33136689, 33136691, 33136693, 33136695, 33136697, 33136699, 33136701, 33136703, 33136705, 33136707, 33136709, 33136711, + 33136713, 33136715, 33136717, 33136719, 33136721, 33136723, 33136725, 33136727, 33136729, 33136731, 33136733, 33136735, 33136737, 33136739, 33136741, + 33136743, 33136745, 33136747, 33136749, 33136751, 33136753, 33136755, 33136757, 33136759, 33136761, 33136763, 33136765, 33136767, 33161089, 33161091, + 33161093, 33161095, 33161097, 33161099, 33161101, 33161103, 33161105, 33161107, 33161109, 33161111, 33161113, 33161115, 33161117, 33161119, 33161121, + 33161123, 33161125, 33161127, 33161129, 33161131, 33161133, 33161135, 33161137, 33161139, 33161141, 33161143, 33161145, 33161147, 33161149, 33161151, + 33161153, 33161155, 33161157, 33161159, 33161161, 33161163, 33161165, 33161167, 33161169, 33161171, 33161173, 33161175, 33161177, 33161179, 33161181, + 33161183, 33161185, 33161187, 33161189, 33161191, 33161193, 33161195, 33161197, 33161199, 33161201, 33161203, 33161205, 33161207, 33161209, 33161211, + 49341, 189, 0, 188, 49340, 33153031, 33153033, 33153035, 33153037, 33153039, 33153041, 33153043, 33153045, 33153047, 33153049, + 33153051, 33153053, 33153055, 33153057, 33153059, 33153061, 33153063, 33153065, 33153067, 33153069, 33153071, 33153073, 33153075, 33153077, 33153079, + 33153081, 33153083, 33153085, 33153087, 33153089, 33153091, 33153093, 33153095, 33153097, 33153099, 33153101, 33153103, 33153105, 33153107, 33153109, + 33153111, 33153113, 33153115, 33153117, 33153119, 33153121, 33153123, 33153125, 33153127, 33153129, 33153131, 33153133, 33153135, 33153137, 33153139, + 33153141, 33153143, 33153145, 33153147, 33153149, 33153151, 33177473, 33177475, 33177477, 33177479, 33177481, 33177483, 33177485, 33177487, 33177489, + 33177491, 33177493, 33177495, 33177497, 33177499, 33177501, 33177503, 33177505, 33177507, 33177509, 33177511, 33177513, 33177515, 33177517, 33177519, + 33177521, 33177523, 33177525, 33177527, 33177529, 33177531, 33177533, 33177535, 33177537, 33177539, 33177541, 33177543, 33177545, 33177547, 33177549, + 33177551, 33177553, 33177555, 33177557, 33177559, 33177561, 33177563, 33177565, 33177567, 33177569, 33177571, 33177573, 33177575, 33177577, 33177579, + 33177581, 33177583, 33177585, 33177587, 33177589, 33177591, 33177593, 33177595, 49343, 191, 0, 190, 49342, 33169415, 33169417, + 33169419, 33169421, 33169423, 33169425, 33169427, 33169429, 33169431, 33169433, 33169435, 33169437, 33169439, 33169441, 33169443, 33169445, 33169447, + 33169449, 33169451, 33169453, 33169455, 33169457, 33169459, 33169461, 33169463, 33169465, 33169467, 33169469, 33169471, 33169473, 33169475, 33169477, + 33169479, 33169481, 33169483, 33169485, 33169487, 33169489, 33169491, 33169493, 33169495, 33169497, 33169499, 33169501, 33169503, 33169505, 33169507, + 33169509, 33169511, 33169513, 33169515, 33169517, 33169519, 33169521, 33169523, 33169525, 33169527, 33169529, 33169531, 33169533, 33169535, 33193857, + 33193859, 33193861, 33193863, 33193865, 33193867, 33193869, 33193871, 33193873, 33193875, 33193877, 33193879, 33193881, 33193883, 33193885, 33193887, + 33193889, 33193891, 33193893, 33193895, 33193897, 33193899, 33193901, 33193903, 33193905, 33193907, 33193909, 33193911, 33193913, 33193915, 33193917, + 33193919, 33193921, 33193923, 33193925, 33193927, 33193929, 33193931, 33193933, 33193935, 33193937, 33193939, 33193941, 33193943, 33193945, 33193947, + 33193949, 33193951, 33193953, 33193955, 33193957, 33193959, 33193961, 33193963, 33193965, 33193967, 33193969, 33193971, 33193973, 33193975, 33193977, + 33193979, 33193981, 463, 0, 462, 33185797, 33185799, 33185801, 33185803, 33185805, 33185807, 33185809, 33185811, 33185813, 33185815, + 33185817, 33185819, 33185821, 33185823, 33185825, 33185827, 33185829, 33185831, 33185833, 33185835, 33185837, 33185839, 33185841, 33185843, 33185845, + 33185847, 33185849, 33185851, 33185853, 33185855, 33185857, 33185859, 33185861, 33185863, 33185865, 33185867, 33185869, 33185871, 33185873, 33185875, + 33185877, 33185879, 33185881, 33185883, 33185885, 33185887, 33185889, 33185891, 33185893, 33185895, 33185897, 33185899, 33185901, 33185903, 33185905, + 33185907, 33185909, 33185911, 33185913, 33185915, 33185917, 33185919, 33210241, 33210243, 33210245, 33210247, 33210249, 33210251, 33210253, 33210255, + 33210257, 33210259, 33210261, 33210263, 33210265, 33210267, 33210269, 33210271, 33210273, 33210275, 33210277, 33210279, 33210281, 33210283, 33210285, + 33210287, 33210289, 33210291, 33210293, 33210295, 33210297, 33210299, 33210301, 33210303, 33210305, 33210307, 33210309, 33210311, 33210313, 33210315, + 33210317, 33210319, 33210321, 33210323, 33210325, 33210327, 33210329, 33210331, 33210333, 33210335, 33210337, 33210339, 33210341, 33210343, 33210345, + 33210347, 33210349, 33210351, 33210353, 33210355, 33210357, 33210359, 33210361, 33210363, 33210365, 1823, 0, 1822, 33202181, 33202183, + 33202185, 33202187, 33202189, 33202191, 33202193, 33202195, 33202197, 33202199, 33202201, 33202203, 33202205, 33202207, 33202209, 33202211, 33202213, + 33202215, 33202217, 33202219, 33202221, 33202223, 33202225, 33202227, 33202229, 33202231, 33202233, 33202235, 33202237, 33202239, 33202241, 33202243, + 33202245, 33202247, 33202249, 33202251, 33202253, 33202255, 33202257, 33202259, 33202261, 33202263, 33202265, 33202267, 33202269, 33202271, 33202273, + 33202275, 33202277, 33202279, 33202281, 33202283, 33202285, 33202287, 33202289, 33202291, 33202293, 33202295, 33202297, 33202299, 33202301, 33202303, + 33226625, 33226627, 33226629, 33226631, 33226633, 33226635, 33226637, 33226639, 33226641, 33226643, 33226645, 33226647, 33226649, 33226651, 33226653, + 33226655, 33226657, 33226659, 33226661, 33226663, 33226665, 33226667, 33226669, 33226671, 33226673, 33226675, 33226677, 33226679, 33226681, 33226683, + 33226685, 33226687, 33226689, 33226691, 33226693, 33226695, 33226697, 33226699, 33226701, 33226703, 33226705, 33226707, 33226709, 33226711, 33226713, + 33226715, 33226717, 33226719, 33226721, 33226723, 33226725, 33226727, 33226729, 33226731, 33226733, 33226735, 33226737, 33226739, 33226741, 33226743, + 33226745, 33226747, 33226749, 1821, 0, 1820, 33218565, 33218567, 33218569, 33218571, 33218573, 33218575, 33218577, 33218579, 33218581, + 33218583, 33218585, 33218587, 33218589, 33218591, 33218593, 33218595, 33218597, 33218599, 33218601, 33218603, 33218605, 33218607, 33218609, 33218611, + 33218613, 33218615, 33218617, 33218619, 33218621, 33218623, 33218625, 33218627, 33218629, 33218631, 33218633, 33218635, 33218637, 33218639, 33218641, + 33218643, 33218645, 33218647, 33218649, 33218651, 33218653, 33218655, 33218657, 33218659, 33218661, 33218663, 33218665, 33218667, 33218669, 33218671, + 33218673, 33218675, 33218677, 33218679, 33218681, 33218683, 33218685, 33218687, 33243009, 33243011, 33243013, 33243015, 33243017, 33243019, 33243021, + 33243023, 33243025, 33243027, 33243029, 33243031, 33243033, 33243035, 33243037, 33243039, 33243041, 33243043, 33243045, 33243047, 33243049, 33243051, + 33243053, 33243055, 33243057, 33243059, 33243061, 33243063, 33243065, 33243067, 33243069, 33243071, 33243073, 33243075, 33243077, 33243079, 33243081, + 33243083, 33243085, 33243087, 33243089, 33243091, 33243093, 33243095, 33243097, 33243099, 33243101, 33243103, 33243105, 33243107, 33243109, 33243111, + 33243113, 33243115, 33243117, 33243119, 33243121, 33243123, 33243125, 33243127, 33243129, 33243131, 33243133, 1819, 0, 1818, 33234949, + 33234951, 33234953, 33234955, 33234957, 33234959, 33234961, 33234963, 33234965, 33234967, 33234969, 33234971, 33234973, 33234975, 33234977, 33234979, + 33234981, 33234983, 33234985, 33234987, 33234989, 33234991, 33234993, 33234995, 33234997, 33234999, 33235001, 33235003, 33235005, 33235007, 33235009, + 33235011, 33235013, 33235015, 33235017, 33235019, 33235021, 33235023, 33235025, 33235027, 33235029, 33235031, 33235033, 33235035, 33235037, 33235039, + 33235041, 33235043, 33235045, 33235047, 33235049, 33235051, 33235053, 33235055, 33235057, 33235059, 33235061, 33235063, 33235065, 33235067, 33235069, + 33235071, 33259393, 33259395, 33259397, 33259399, 33259401, 33259403, 33259405, 33259407, 33259409, 33259411, 33259413, 33259415, 33259417, 33259419, + 33259421, 33259423, 33259425, 33259427, 33259429, 33259431, 33259433, 33259435, 33259437, 33259439, 33259441, 33259443, 33259445, 33259447, 33259449, + 33259451, 33259453, 33259455, 33259457, 33259459, 33259461, 33259463, 33259465, 33259467, 33259469, 33259471, 33259473, 33259475, 33259477, 33259479, + 33259481, 33259483, 33259485, 33259487, 33259489, 33259491, 33259493, 33259495, 33259497, 33259499, 33259501, 33259503, 33259505, 33259507, 33259509, + 33259511, 33259513, 33259515, 33259517, 1817, 0, 1816, 33251333, 33251335, 33251337, 33251339, 33251341, 33251343, 33251345, 33251347, + 33251349, 33251351, 33251353, 33251355, 33251357, 33251359, 33251361, 33251363, 33251365, 33251367, 33251369, 33251371, 33251373, 33251375, 33251377, + 33251379, 33251381, 33251383, 33251385, 33251387, 33251389, 33251391, 33251393, 33251395, 33251397, 33251399, 33251401, 33251403, 33251405, 33251407, + 33251409, 33251411, 33251413, 33251415, 33251417, 33251419, 33251421, 33251423, 33251425, 33251427, 33251429, 33251431, 33251433, 33251435, 33251437, + 33251439, 33251441, 33251443, 33251445, 33251447, 33251449, 33251451, 33251453, 33251455, 33275777, 33275779, 33275781, 33275783, 33275785, 33275787, + 33275789, 33275791, 33275793, 33275795, 33275797, 33275799, 33275801, 33275803, 33275805, 33275807, 33275809, 33275811, 33275813, 33275815, 33275817, + 33275819, 33275821, 33275823, 33275825, 33275827, 33275829, 33275831, 33275833, 33275835, 33275837, 33275839, 33275841, 33275843, 33275845, 33275847, + 33275849, 33275851, 33275853, 33275855, 33275857, 33275859, 33275861, 33275863, 33275865, 33275867, 33275869, 33275871, 33275873, 33275875, 33275877, + 33275879, 33275881, 33275883, 33275885, 33275887, 33275889, 33275891, 33275893, 33275895, 33275897, 33275899, 33275901, 3623, 0, 3622, + 33267717, 33267719, 33267721, 33267723, 33267725, 33267727, 33267729, 33267731, 33267733, 33267735, 33267737, 33267739, 33267741, 33267743, 33267745, + 33267747, 33267749, 33267751, 33267753, 33267755, 33267757, 33267759, 33267761, 33267763, 33267765, 33267767, 33267769, 33267771, 33267773, 33267775, + 33267777, 33267779, 33267781, 33267783, 33267785, 33267787, 33267789, 33267791, 33267793, 33267795, 33267797, 33267799, 33267801, 33267803, 33267805, + 33267807, 33267809, 33267811, 33267813, 33267815, 33267817, 33267819, 33267821, 33267823, 33267825, 33267827, 33267829, 33267831, 33267833, 33267835, + 33267837, 33267839, 33292161, 33292163, 33292165, 33292167, 33292169, 33292171, 33292173, 33292175, 33292177, 33292179, 33292181, 33292183, 33292185, + 33292187, 33292189, 33292191, 33292193, 33292195, 33292197, 33292199, 33292201, 33292203, 33292205, 33292207, 33292209, 33292211, 33292213, 33292215, + 33292217, 33292219, 33292221, 33292223, 33292225, 33292227, 33292229, 33292231, 33292233, 33292235, 33292237, 33292239, 33292241, 33292243, 33292245, + 33292247, 33292249, 33292251, 33292253, 33292255, 33292257, 33292259, 33292261, 33292263, 33292265, 33292267, 33292269, 33292271, 33292273, 33292275, + 33292277, 33292279, 33292281, 33292283, 33292285, 3621, 0, 3620, 33284101, 33284103, 33284105, 33284107, 33284109, 33284111, 33284113, + 33284115, 33284117, 33284119, 33284121, 33284123, 33284125, 33284127, 33284129, 33284131, 33284133, 33284135, 33284137, 33284139, 33284141, 33284143, + 33284145, 33284147, 33284149, 33284151, 33284153, 33284155, 33284157, 33284159, 33284161, 33284163, 33284165, 33284167, 33284169, 33284171, 33284173, + 33284175, 33284177, 33284179, 33284181, 33284183, 33284185, 33284187, 33284189, 33284191, 33284193, 33284195, 33284197, 33284199, 33284201, 33284203, + 33284205, 33284207, 33284209, 33284211, 33284213, 33284215, 33284217, 33284219, 33284221, 33284223, 33308545, 33308547, 33308549, 33308551, 33308553, + 33308555, 33308557, 33308559, 33308561, 33308563, 33308565, 33308567, 33308569, 33308571, 33308573, 33308575, 33308577, 33308579, 33308581, 33308583, + 33308585, 33308587, 33308589, 33308591, 33308593, 33308595, 33308597, 33308599, 33308601, 33308603, 33308605, 33308607, 33308609, 33308611, 33308613, + 33308615, 33308617, 33308619, 33308621, 33308623, 33308625, 33308627, 33308629, 33308631, 33308633, 33308635, 33308637, 33308639, 33308641, 33308643, + 33308645, 33308647, 33308649, 33308651, 33308653, 33308655, 33308657, 33308659, 33308661, 33308663, 33308665, 33308667, 33308669, 3619, 0, + 3618, 33300485, 33300487, 33300489, 33300491, 33300493, 33300495, 33300497, 33300499, 33300501, 33300503, 33300505, 33300507, 33300509, 33300511, + 33300513, 33300515, 33300517, 33300519, 33300521, 33300523, 33300525, 33300527, 33300529, 33300531, 33300533, 33300535, 33300537, 33300539, 33300541, + 33300543, 33300545, 33300547, 33300549, 33300551, 33300553, 33300555, 33300557, 33300559, 33300561, 33300563, 33300565, 33300567, 33300569, 33300571, + 33300573, 33300575, 33300577, 33300579, 33300581, 33300583, 33300585, 33300587, 33300589, 33300591, 33300593, 33300595, 33300597, 33300599, 33300601, + 33300603, 33300605, 33300607, 33324929, 33324931, 33324933, 33324935, 33324937, 33324939, 33324941, 33324943, 33324945, 33324947, 33324949, 33324951, + 33324953, 33324955, 33324957, 33324959, 33324961, 33324963, 33324965, 33324967, 33324969, 33324971, 33324973, 33324975, 33324977, 33324979, 33324981, + 33324983, 33324985, 33324987, 33324989, 33324991, 33324993, 33324995, 33324997, 33324999, 33325001, 33325003, 33325005, 33325007, 33325009, 33325011, + 33325013, 33325015, 33325017, 33325019, 33325021, 33325023, 33325025, 33325027, 33325029, 33325031, 33325033, 33325035, 33325037, 33325039, 33325041, + 33325043, 33325045, 33325047, 33325049, 33325051, 33325053, 3617, 0, 3616, 33316869, 33316871, 33316873, 33316875, 33316877, 33316879, + 33316881, 33316883, 33316885, 33316887, 33316889, 33316891, 33316893, 33316895, 33316897, 33316899, 33316901, 33316903, 33316905, 33316907, 33316909, + 33316911, 33316913, 33316915, 33316917, 33316919, 33316921, 33316923, 33316925, 33316927, 33316929, 33316931, 33316933, 33316935, 33316937, 33316939, + 33316941, 33316943, 33316945, 33316947, 33316949, 33316951, 33316953, 33316955, 33316957, 33316959, 33316961, 33316963, 33316965, 33316967, 33316969, + 33316971, 33316973, 33316975, 33316977, 33316979, 33316981, 33316983, 33316985, 33316987, 33316989, 33316991, 33341313, 33341315, 33341317, 33341319, + 33341321, 33341323, 33341325, 33341327, 33341329, 33341331, 33341333, 33341335, 33341337, 33341339, 33341341, 33341343, 33341345, 33341347, 33341349, + 33341351, 33341353, 33341355, 33341357, 33341359, 33341361, 33341363, 33341365, 33341367, 33341369, 33341371, 33341373, 33341375, 33341377, 33341379, + 33341381, 33341383, 33341385, 33341387, 33341389, 33341391, 33341393, 33341395, 33341397, 33341399, 33341401, 33341403, 33341405, 33341407, 33341409, + 33341411, 33341413, 33341415, 33341417, 33341419, 33341421, 33341423, 33341425, 33341427, 33341429, 33341431, 33341433, 33341435, 33341437, 7221, + 0, 7220, 33333253, 33333255, 33333257, 33333259, 33333261, 33333263, 33333265, 33333267, 33333269, 33333271, 33333273, 33333275, 33333277, + 33333279, 33333281, 33333283, 33333285, 33333287, 33333289, 33333291, 33333293, 33333295, 33333297, 33333299, 33333301, 33333303, 33333305, 33333307, + 33333309, 33333311, 33333313, 33333315, 33333317, 33333319, 33333321, 33333323, 33333325, 33333327, 33333329, 33333331, 33333333, 33333335, 33333337, + 33333339, 33333341, 33333343, 33333345, 33333347, 33333349, 33333351, 33333353, 33333355, 33333357, 33333359, 33333361, 33333363, 33333365, 33333367, + 33333369, 33333371, 33333373, 33333375, 33357697, 33357699, 33357701, 33357703, 33357705, 33357707, 33357709, 33357711, 33357713, 33357715, 33357717, + 33357719, 33357721, 33357723, 33357725, 33357727, 33357729, 33357731, 33357733, 33357735, 33357737, 33357739, 33357741, 33357743, 33357745, 33357747, + 33357749, 33357751, 33357753, 33357755, 33357757, 33357759, 33357761, 33357763, 33357765, 33357767, 33357769, 33357771, 33357773, 33357775, 33357777, + 33357779, 33357781, 33357783, 33357785, 33357787, 33357789, 33357791, 33357793, 33357795, 33357797, 33357799, 33357801, 33357803, 33357805, 33357807, + 33357809, 33357811, 33357813, 33357815, 33357817, 33357819, 33357821, 7219, 0, 7218, 33349637, 33349639, 33349641, 33349643, 33349645, + 33349647, 33349649, 33349651, 33349653, 33349655, 33349657, 33349659, 33349661, 33349663, 33349665, 33349667, 33349669, 33349671, 33349673, 33349675, + 33349677, 33349679, 33349681, 33349683, 33349685, 33349687, 33349689, 33349691, 33349693, 33349695, 33349697, 33349699, 33349701, 33349703, 33349705, + 33349707, 33349709, 33349711, 33349713, 33349715, 33349717, 33349719, 33349721, 33349723, 33349725, 33349727, 33349729, 33349731, 33349733, 33349735, + 33349737, 33349739, 33349741, 33349743, 33349745, 33349747, 33349749, 33349751, 33349753, 33349755, 33349757, 33349759, 33374081, 33374083, 33374085, + 33374087, 33374089, 33374091, 33374093, 33374095, 33374097, 33374099, 33374101, 33374103, 33374105, 33374107, 33374109, 33374111, 33374113, 33374115, + 33374117, 33374119, 33374121, 33374123, 33374125, 33374127, 33374129, 33374131, 33374133, 33374135, 33374137, 33374139, 33374141, 33374143, 33374145, + 33374147, 33374149, 33374151, 33374153, 33374155, 33374157, 33374159, 33374161, 33374163, 33374165, 33374167, 33374169, 33374171, 33374173, 33374175, + 33374177, 33374179, 33374181, 33374183, 33374185, 33374187, 33374189, 33374191, 33374193, 33374195, 33374197, 33374199, 33374201, 33374203, 33374205, + 7217, 0, 7216, 33366021, 33366023, 33366025, 33366027, 33366029, 33366031, 33366033, 33366035, 33366037, 33366039, 33366041, 33366043, + 33366045, 33366047, 33366049, 33366051, 33366053, 33366055, 33366057, 33366059, 33366061, 33366063, 33366065, 33366067, 33366069, 33366071, 33366073, + 33366075, 33366077, 33366079, 33366081, 33366083, 33366085, 33366087, 33366089, 33366091, 33366093, 33366095, 33366097, 33366099, 33366101, 33366103, + 33366105, 33366107, 33366109, 33366111, 33366113, 33366115, 33366117, 33366119, 33366121, 33366123, 33366125, 33366127, 33366129, 33366131, 33366133, + 33366135, 33366137, 33366139, 33366141, 33366143, 33390465, 33390467, 33390469, 33390471, 33390473, 33390475, 33390477, 33390479, 33390481, 33390483, + 33390485, 33390487, 33390489, 33390491, 33390493, 33390495, 33390497, 33390499, 33390501, 33390503, 33390505, 33390507, 33390509, 33390511, 33390513, + 33390515, 33390517, 33390519, 33390521, 33390523, 33390525, 33390527, 33390529, 33390531, 33390533, 33390535, 33390537, 33390539, 33390541, 33390543, + 33390545, 33390547, 33390549, 33390551, 33390553, 33390555, 33390557, 33390559, 33390561, 33390563, 33390565, 33390567, 33390569, 33390571, 33390573, + 33390575, 33390577, 33390579, 33390581, 33390583, 33390585, 33390587, 33390589, 7215, 0, 7214, 33382405, 33382407, 33382409, 33382411, + 33382413, 33382415, 33382417, 33382419, 33382421, 33382423, 33382425, 33382427, 33382429, 33382431, 33382433, 33382435, 33382437, 33382439, 33382441, + 33382443, 33382445, 33382447, 33382449, 33382451, 33382453, 33382455, 33382457, 33382459, 33382461, 33382463, 33382465, 33382467, 33382469, 33382471, + 33382473, 33382475, 33382477, 33382479, 33382481, 33382483, 33382485, 33382487, 33382489, 33382491, 33382493, 33382495, 33382497, 33382499, 33382501, + 33382503, 33382505, 33382507, 33382509, 33382511, 33382513, 33382515, 33382517, 33382519, 33382521, 33382523, 33382525, 33382527, 33406849, 33406851, + 33406853, 33406855, 33406857, 33406859, 33406861, 33406863, 33406865, 33406867, 33406869, 33406871, 33406873, 33406875, 33406877, 33406879, 33406881, + 33406883, 33406885, 33406887, 33406889, 33406891, 33406893, 33406895, 33406897, 33406899, 33406901, 33406903, 33406905, 33406907, 33406909, 33406911, + 33406913, 33406915, 33406917, 33406919, 33406921, 33406923, 33406925, 33406927, 33406929, 33406931, 33406933, 33406935, 33406937, 33406939, 33406941, + 33406943, 33406945, 33406947, 33406949, 33406951, 33406953, 33406955, 33406957, 33406959, 33406961, 33406963, 33406965, 33406967, 33406969, 33406971, + 33406973, 7213, 0, 7212, 33398789, 33398791, 33398793, 33398795, 33398797, 33398799, 33398801, 33398803, 33398805, 33398807, 33398809, + 33398811, 33398813, 33398815, 33398817, 33398819, 33398821, 33398823, 33398825, 33398827, 33398829, 33398831, 33398833, 33398835, 33398837, 33398839, + 33398841, 33398843, 33398845, 33398847, 33398849, 33398851, 33398853, 33398855, 33398857, 33398859, 33398861, 33398863, 33398865, 33398867, 33398869, + 33398871, 33398873, 33398875, 33398877, 33398879, 33398881, 33398883, 33398885, 33398887, 33398889, 33398891, 33398893, 33398895, 33398897, 33398899, + 33398901, 33398903, 33398905, 33398907, 33398909, 33398911, 33423233, 33423235, 33423237, 33423239, 33423241, 33423243, 33423245, 33423247, 33423249, + 33423251, 33423253, 33423255, 33423257, 33423259, 33423261, 33423263, 33423265, 33423267, 33423269, 33423271, 33423273, 33423275, 33423277, 33423279, + 33423281, 33423283, 33423285, 33423287, 33423289, 33423291, 33423293, 33423295, 33423297, 33423299, 33423301, 33423303, 33423305, 33423307, 33423309, + 33423311, 33423313, 33423315, 33423317, 33423319, 33423321, 33423323, 33423325, 33423327, 33423329, 33423331, 33423333, 33423335, 33423337, 33423339, + 33423341, 33423343, 33423345, 33423347, 33423349, 33423351, 33423353, 33423355, 33423357, 7211, 0, 7210, 33415173, 33415175, 33415177, + 33415179, 33415181, 33415183, 33415185, 33415187, 33415189, 33415191, 33415193, 33415195, 33415197, 33415199, 33415201, 33415203, 33415205, 33415207, + 33415209, 33415211, 33415213, 33415215, 33415217, 33415219, 33415221, 33415223, 33415225, 33415227, 33415229, 33415231, 33415233, 33415235, 33415237, + 33415239, 33415241, 33415243, 33415245, 33415247, 33415249, 33415251, 33415253, 33415255, 33415257, 33415259, 33415261, 33415263, 33415265, 33415267, + 33415269, 33415271, 33415273, 33415275, 33415277, 33415279, 33415281, 33415283, 33415285, 33415287, 33415289, 33415291, 33415293, 33415295, 33439617, + 33439619, 33439621, 33439623, 33439625, 33439627, 33439629, 33439631, 33439633, 33439635, 33439637, 33439639, 33439641, 33439643, 33439645, 33439647, + 33439649, 33439651, 33439653, 33439655, 33439657, 33439659, 33439661, 33439663, 33439665, 33439667, 33439669, 33439671, 33439673, 33439675, 33439677, + 33439679, 33439681, 33439683, 33439685, 33439687, 33439689, 33439691, 33439693, 33439695, 33439697, 33439699, 33439701, 33439703, 33439705, 33439707, + 33439709, 33439711, 33439713, 33439715, 33439717, 33439719, 33439721, 33439723, 33439725, 33439727, 33439729, 33439731, 33439733, 33439735, 33439737, + 33439739, 33439741, 7209, 0, 7208, 33431557, 33431559, 33431561, 33431563, 33431565, 33431567, 33431569, 33431571, 33431573, 33431575, + 33431577, 33431579, 33431581, 33431583, 33431585, 33431587, 33431589, 33431591, 33431593, 33431595, 33431597, 33431599, 33431601, 33431603, 33431605, + 33431607, 33431609, 33431611, 33431613, 33431615, 33431617, 33431619, 33431621, 33431623, 33431625, 33431627, 33431629, 33431631, 33431633, 33431635, + 33431637, 33431639, 33431641, 33431643, 33431645, 33431647, 33431649, 33431651, 33431653, 33431655, 33431657, 33431659, 33431661, 33431663, 33431665, + 33431667, 33431669, 33431671, 33431673, 33431675, 33431677, 33431679, 33456001, 33456003, 33456005, 33456007, 33456009, 33456011, 33456013, 33456015, + 33456017, 33456019, 33456021, 33456023, 33456025, 33456027, 33456029, 33456031, 33456033, 33456035, 33456037, 33456039, 33456041, 33456043, 33456045, + 33456047, 33456049, 33456051, 33456053, 33456055, 33456057, 33456059, 33456061, 33456063, 33456065, 33456067, 33456069, 33456071, 33456073, 33456075, + 33456077, 33456079, 33456081, 33456083, 33456085, 33456087, 33456089, 33456091, 33456093, 33456095, 33456097, 33456099, 33456101, 33456103, 33456105, + 33456107, 33456109, 33456111, 33456113, 33456115, 33456117, 33456119, 33456121, 33456123, 33456125, 7207, 0, 7206, 33447941, 33447943, + 33447945, 33447947, 33447949, 33447951, 33447953, 33447955, 33447957, 33447959, 33447961, 33447963, 33447965, 33447967, 33447969, 33447971, 33447973, + 33447975, 33447977, 33447979, 33447981, 33447983, 33447985, 33447987, 33447989, 33447991, 33447993, 33447995, 33447997, 33447999, 33448001, 33448003, + 33448005, 33448007, 33448009, 33448011, 33448013, 33448015, 33448017, 33448019, 33448021, 33448023, 33448025, 33448027, 33448029, 33448031, 33448033, + 33448035, 33448037, 33448039, 33448041, 33448043, 33448045, 33448047, 33448049, 33448051, 33448053, 33448055, 33448057, 33448059, 33448061, 33448063, + 33472385, 33472387, 33472389, 33472391, 33472393, 33472395, 33472397, 33472399, 33472401, 33472403, 33472405, 33472407, 33472409, 33472411, 33472413, + 33472415, 33472417, 33472419, 33472421, 33472423, 33472425, 33472427, 33472429, 33472431, 33472433, 33472435, 33472437, 33472439, 33472441, 33472443, + 33472445, 33472447, 33472449, 33472451, 33472453, 33472455, 33472457, 33472459, 33472461, 33472463, 33472465, 33472467, 33472469, 33472471, 33472473, + 33472475, 33472477, 33472479, 33472481, 33472483, 33472485, 33472487, 33472489, 33472491, 33472493, 33472495, 33472497, 33472499, 33472501, 33472503, + 33472505, 33472507, 33472509, 14385, 0, 14384, 33464325, 33464327, 33464329, 33464331, 33464333, 33464335, 33464337, 33464339, 33464341, + 33464343, 33464345, 33464347, 33464349, 33464351, 33464353, 33464355, 33464357, 33464359, 33464361, 33464363, 33464365, 33464367, 33464369, 33464371, + 33464373, 33464375, 33464377, 33464379, 33464381, 33464383, 33464385, 33464387, 33464389, 33464391, 33464393, 33464395, 33464397, 33464399, 33464401, + 33464403, 33464405, 33464407, 33464409, 33464411, 33464413, 33464415, 33464417, 33464419, 33464421, 33464423, 33464425, 33464427, 33464429, 33464431, + 33464433, 33464435, 33464437, 33464439, 33464441, 33464443, 33464445, 33464447, 33488769, 33488771, 33488773, 33488775, 33488777, 33488779, 33488781, + 33488783, 33488785, 33488787, 33488789, 33488791, 33488793, 33488795, 33488797, 33488799, 33488801, 33488803, 33488805, 33488807, 33488809, 33488811, + 33488813, 33488815, 33488817, 33488819, 33488821, 33488823, 33488825, 33488827, 33488829, 33488831, 33488833, 33488835, 33488837, 33488839, 33488841, + 33488843, 33488845, 33488847, 33488849, 33488851, 33488853, 33488855, 33488857, 33488859, 33488861, 33488863, 33488865, 33488867, 33488869, 33488871, + 33488873, 33488875, 33488877, 33488879, 33488881, 33488883, 33488885, 33488887, 33488889, 33488891, 33488893, 14383, 0, 14382, 33480709, + 33480711, 33480713, 33480715, 33480717, 33480719, 33480721, 33480723, 33480725, 33480727, 33480729, 33480731, 33480733, 33480735, 33480737, 33480739, + 33480741, 33480743, 33480745, 33480747, 33480749, 33480751, 33480753, 33480755, 33480757, 33480759, 33480761, 33480763, 33480765, 33480767, 33480769, + 33480771, 33480773, 33480775, 33480777, 33480779, 33480781, 33480783, 33480785, 33480787, 33480789, 33480791, 33480793, 33480795, 33480797, 33480799, + 33480801, 33480803, 33480805, 33480807, 33480809, 33480811, 33480813, 33480815, 33480817, 33480819, 33480821, 33480823, 33480825, 33480827, 33480829, + 33480831, 33505153, 33505155, 33505157, 33505159, 33505161, 33505163, 33505165, 33505167, 33505169, 33505171, 33505173, 33505175, 33505177, 33505179, + 33505181, 33505183, 33505185, 33505187, 33505189, 33505191, 33505193, 33505195, 33505197, 33505199, 33505201, 33505203, 33505205, 33505207, 33505209, + 33505211, 33505213, 33505215, 33505217, 33505219, 33505221, 33505223, 33505225, 33505227, 33505229, 33505231, 33505233, 33505235, 33505237, 33505239, + 33505241, 33505243, 33505245, 33505247, 33505249, 33505251, 33505253, 33505255, 33505257, 33505259, 33505261, 33505263, 33505265, 33505267, 33505269, + 33505271, 33505273, 33505275, 33505277, 14381, 0, 14380, 33497093, 33497095, 33497097, 33497099, 33497101, 33497103, 33497105, 33497107, + 33497109, 33497111, 33497113, 33497115, 33497117, 33497119, 33497121, 33497123, 33497125, 33497127, 33497129, 33497131, 33497133, 33497135, 33497137, + 33497139, 33497141, 33497143, 33497145, 33497147, 33497149, 33497151, 33497153, 33497155, 33497157, 33497159, 33497161, 33497163, 33497165, 33497167, + 33497169, 33497171, 33497173, 33497175, 33497177, 33497179, 33497181, 33497183, 33497185, 33497187, 33497189, 33497191, 33497193, 33497195, 33497197, + 33497199, 33497201, 33497203, 33497205, 33497207, 33497209, 33497211, 33497213, 33497215, 33521537, 33521539, 33521541, 33521543, 33521545, 33521547, + 33521549, 33521551, 33521553, 33521555, 33521557, 33521559, 33521561, 33521563, 33521565, 33521567, 33521569, 33521571, 33521573, 33521575, 33521577, + 33521579, 33521581, 33521583, 33521585, 33521587, 33521589, 33521591, 33521593, 33521595, 33521597, 33521599, 33521601, 33521603, 33521605, 33521607, + 33521609, 33521611, 33521613, 33521615, 33521617, 33521619, 33521621, 33521623, 33521625, 33521627, 33521629, 33521631, 33521633, 33521635, 33521637, + 33521639, 33521641, 33521643, 33521645, 33521647, 33521649, 33521651, 33521653, 33521655, 33521657, 33521659, 33521661, 14379, 0, 14378, + 33513477, 33513479, 33513481, 33513483, 33513485, 33513487, 33513489, 33513491, 33513493, 33513495, 33513497, 33513499, 33513501, 33513503, 33513505, + 33513507, 33513509, 33513511, 33513513, 33513515, 33513517, 33513519, 33513521, 33513523, 33513525, 33513527, 33513529, 33513531, 33513533, 33513535, + 33513537, 33513539, 33513541, 33513543, 33513545, 33513547, 33513549, 33513551, 33513553, 33513555, 33513557, 33513559, 33513561, 33513563, 33513565, + 33513567, 33513569, 33513571, 33513573, 33513575, 33513577, 33513579, 33513581, 33513583, 33513585, 33513587, 33513589, 33513591, 33513593, 33513595, + 33513597, 33513599, 33537921, 33537923, 33537925, 33537927, 33537929, 33537931, 33537933, 33537935, 33537937, 33537939, 33537941, 33537943, 33537945, + 33537947, 33537949, 33537951, 33537953, 33537955, 33537957, 33537959, 33537961, 33537963, 33537965, 33537967, 33537969, 33537971, 33537973, 33537975, + 33537977, 33537979, 33537981, 33537983, 33537985, 33537987, 33537989, 33537991, 33537993, 33537995, 33537997, 33537999, 33538001, 33538003, 33538005, + 33538007, 33538009, 33538011, 33538013, 33538015, 33538017, 33538019, 33538021, 33538023, 33538025, 33538027, 33538029, 33538031, 33538033, 33538035, + 33538037, 33538039, 33538041, 33538043, 33538045, 14377, 0, 14376, 33529861, 33529863, 33529865, 33529867, 33529869, 33529871, 33529873, + 33529875, 33529877, 33529879, 33529881, 33529883, 33529885, 33529887, 33529889, 33529891, 33529893, 33529895, 33529897, 33529899, 33529901, 33529903, + 33529905, 33529907, 33529909, 33529911, 33529913, 33529915, 33529917, 33529919, 33529921, 33529923, 33529925, 33529927, 33529929, 33529931, 33529933, + 33529935, 33529937, 33529939, 33529941, 33529943, 33529945, 33529947, 33529949, 33529951, 33529953, 33529955, 33529957, 33529959, 33529961, 33529963, + 33529965, 33529967, 33529969, 33529971, 33529973, 33529975, 33529977, 33529979, 33529981, 33529983, 33554305, 33554307, 33554309, 33554311, 33554313, + 33554315, 33554317, 33554319, 33554321, 33554323, 33554325, 33554327, 33554329, 33554331, 33554333, 33554335, 33554337, 33554339, 33554341, 33554343, + 33554345, 33554347, 33554349, 33554351, 33554353, 33554355, 33554357, 33554359, 33554361, 33554363, 33554365, 33554367, 33554369, 33554371, 33554373, + 33554375, 33554377, 33554379, 33554381, 33554383, 33554385, 33554387, 33554389, 33554391, 33554393, 33554395, 33554397, 33554399, 33554401, 33554403, + 33554405, 33554407, 33554409, 33554411, 33554413, 33554415, 33554417, 33554419, 33554421, 33554423, 33554425, 33554427, 33554429, 14375, 0, + 14374, 33546245, 33546247, 33546249, 33546251, 33546253, 33546255, 33546257, 33546259, 33546261, 33546263, 33546265, 33546267, 33546269, 33546271, + 33546273, 33546275, 33546277, 33546279, 33546281, 33546283, 33546285, 33546287, 33546289, 33546291, 33546293, 33546295, 33546297, 33546299, 33546301, + 33546303, 33546305, 33546307, 33546309, 33546311, 33546313, 33546315, 33546317, 33546319, 33546321, 33546323, 33546325, 33546327, 33546329, 33546331, + 33546333, 33546335, 33546337, 33546339, 33546341, 33546343, 33546345, 33546347, 33546349, 33546351, 33546353, 33546355, 33546357, 33546359, 33546361, + 33546363, 33546365, 33546367 +}; + +static const uint8 uni_mpeg4_inter_rl_len[] = +{ + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, + 20, 20, 19, 19, 18, 18, 17, 16, 15, 13, 11, 12, 12, 12, 11, 11, 10, 10, 9, 8, + 7, 5, 3, 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 12, 12, 11, 13, 15, 16, + 17, 18, 18, 19, 19, 20, 20, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, + 20, 19, 17, 15, 12, 13, 12, 11, 9, 7, 4, 0, 4, 7, 9, 11, 12, 13, 12, 15, + 17, 19, 20, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 19, 17, 13, 13, 11, 9, 5, 0, + 5, 9, 11, 13, 13, 17, 19, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 19, 18, 14, 11, 10, 6, 0, 6, 10, 11, 14, 18, 19, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 18, 14, 13, 10, 6, 0, 6, 10, 13, 14, + 18, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 19, 14, + 13, 11, 6, 0, 6, 11, 13, 14, 19, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 21, 19, 15, 13, 11, 7, 0, 7, 11, 13, 15, 19, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 15, 11, 7, 0, + 7, 11, 15, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 19, 15, 11, 7, 0, 7, 11, 15, 19, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 15, 11, 7, 0, 7, 11, 15, 19, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, + 16, 13, 8, 0, 8, 13, 16, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 22, 14, 8, 0, 8, 14, 22, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 16, 8, 0, + 8, 16, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 22, 17, 9, 0, 9, 17, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, + 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, + 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 12, 0, + 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 13, 0, 13, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 14, 0, 14, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 15, 0, 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 15, 0, 15, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 15, 0, + 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, + 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 21, 0, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 0, 21, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 22, 0, + 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 22, 0, 22, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 18, 13, 12, 10, 5, 0, 5, 10, 12, 13, + 18, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, + 15, 12, 7, 0, 7, 12, 15, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 15, 7, 0, 7, 15, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 15, 7, 0, + 7, 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 15, 7, 0, 7, 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 8, 0, 8, 16, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 16, 8, 0, 8, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 8, 0, 8, 16, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 8, 0, + 8, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, + 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 9, 0, 9, 17, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 17, 9, 0, 9, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, + 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 10, 0, + 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 18, 10, 0, 10, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 11, 0, 11, 19, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 19, 11, 0, 11, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 11, 0, 11, 19, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 11, 0, + 11, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 20, 12, 0, 12, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 12, 0, 12, 20, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, + 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, + 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 21, 13, 0, 13, 21, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 14, 0, 14, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, + 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 16, 0, 16, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 0, + 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 17, 0, 17, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, + 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 18, 0, 18, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, 19, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 19, 0, + 19, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30 +}; + +#endif // M4VENCODE_TABLES_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/type.h b/libeplayer3-arm/external/flv2mpeg4/src/type.h new file mode 100644 index 0000000..48b4ab0 --- /dev/null +++ b/libeplayer3-arm/external/flv2mpeg4/src/type.h @@ -0,0 +1,46 @@ +/* + * types + * + * Copyright (c) 2006 vixy project + * + * This file is part of VIXY FLV Converter. + * + * 'VIXY FLV Converter' is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 'VIXY FLV Converter' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TYPE_H +#define TYPE_H + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct _VLCDEC +{ + int bits; + int value; + + int bits_ex; + int value_ex; + +} VLCDEC; + +#endif // TYPE_H diff --git a/libeplayer3-arm/include/aac.h b/libeplayer3-arm/include/aac.h new file mode 100644 index 0000000..a50f7de --- /dev/null +++ b/libeplayer3-arm/include/aac.h @@ -0,0 +1,67 @@ +/* + * aac helper + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef acc_123 +#define acc_123 + +#define AAC_HEADER_LENGTH 7 + +static inline int HasADTSHeader(uint8_t *data, int size) +{ + if (size >= AAC_HEADER_LENGTH && 0xFF == data[0] && 0xF0 == 0xF0 & data[1] && + size == ((data[3] & 0x3) << 11 | data[4] << 3 | data[5] >> 5)) + { + return 1; + } + return 0; +} + +static inline int aac_get_sample_rate_index(uint32_t sample_rate) +{ + if (96000 <= sample_rate) + return 0; + else if (88200 <= sample_rate) + return 1; + else if (64000 <= sample_rate) + return 2; + else if (48000 <= sample_rate) + return 3; + else if (44100 <= sample_rate) + return 4; + else if (32000 <= sample_rate) + return 5; + else if (24000 <= sample_rate) + return 6; + else if (22050 <= sample_rate) + return 7; + else if (16000 <= sample_rate) + return 8; + else if (12000 <= sample_rate) + return 9; + else if (11025 <= sample_rate) + return 10; + else if (8000 <= sample_rate) + return 11; + else if (7350 <= sample_rate) + return 12; + else + return 13; +} + +#endif diff --git a/libeplayer3-arm/include/bcm_ioctls.h b/libeplayer3-arm/include/bcm_ioctls.h new file mode 100644 index 0000000..d52f298 --- /dev/null +++ b/libeplayer3-arm/include/bcm_ioctls.h @@ -0,0 +1,85 @@ +/* + * bcm_ioctls.h + * + * + * + * + */ + +#ifndef H_DVB_BCM_H +#define H_DVB_BCM_H + +#include + +typedef struct video_codec_data +{ + int32_t length; + uint8_t *data; +} video_codec_data_t; +#define VIDEO_SET_CODEC_DATA _IOW('o', 80, video_codec_data_t) + +typedef enum +{ + CT_MPEG1, + CT_MPEG2, + CT_H264, + CT_DIVX311, + CT_DIVX4, + CT_MPEG4_PART2, + CT_VC1, + CT_VC1_SM, + CT_H265, + CT_SPARK, + CT_VP6, + CT_VP8, + CT_VP9 +} video_codec_type_t; + + +typedef enum +{ + STREAMTYPE_UNKNOWN = -1, + STREAMTYPE_MPEG2 = 0, + STREAMTYPE_MPEG4_H264 = 1, + STREAMTYPE_H263 = 2, + STREAMTYPE_VC1 = 3, + STREAMTYPE_MPEG4_Part2 = 4, + STREAMTYPE_VC1_SM = 5, + STREAMTYPE_MPEG1 = 6, + STREAMTYPE_MPEG4_H265 = 7, + STREAMTYPE_VB8 = 8, + STREAMTYPE_VB9 = 9, + STREAMTYPE_XVID = 10, + STREAMTYPE_DIVX311 = 13, + STREAMTYPE_DIVX4 = 14, + STREAMTYPE_DIVX5 = 15, + STREAMTYPE_VB6 = 18, + STREAMTYPE_SPARK = 21, +} video_stream_type_t; + + + +typedef enum +{ + AUDIOTYPE_UNKNOWN = -1, + AUDIOTYPE_AC3 = 0, + AUDIOTYPE_MPEG = 1, + AUDIOTYPE_DTS = 2, + AUDIOTYPE_LPCM = 6, + AUDIOTYPE_AAC = 8, + AUDIOTYPE_AAC_HE = 9, + AUDIOTYPE_MP3 = 0xa, + AUDIOTYPE_AAC_PLUS = 0xb, + AUDIOTYPE_DTS_HD = 0x10, + AUDIOTYPE_WMA = 0x20, + AUDIOTYPE_WMA_PRO = 0x21, + AUDIOTYPE_AC3_PLUS = 0x22, + AUDIOTYPE_AMR = 0x23, + AUDIOTYPE_RAW = 0xf +} audio_stream_type_t; + + + + +#endif /* H_DVB_BCM_H */ + diff --git a/libeplayer3-arm/include/common.h b/libeplayer3-arm/include/common.h new file mode 100644 index 0000000..ac26ac0 --- /dev/null +++ b/libeplayer3-arm/include/common.h @@ -0,0 +1,29 @@ +#ifndef COMMON_H_ +#define COMMON_H_ + +#include + +#include "container.h" +#include "output.h" +#include "manager.h" +#include "playback.h" +#include + +typedef char PlayFilesTab_t[2]; + +typedef struct PlayFiles_t +{ + char *szFirstFile; + char *szSecondFile; +} PlayFiles_t; + +typedef struct Context_s +{ + PlaybackHandler_t *playback; + ContainerHandler_t *container; + OutputHandler_t *output; + ManagerHandler_t *manager; +} Context_t; + +int container_ffmpeg_update_tracks(Context_t *context, char *filename, int initial); +#endif diff --git a/libeplayer3-arm/include/container.h b/libeplayer3-arm/include/container.h new file mode 100644 index 0000000..e3f32a1 --- /dev/null +++ b/libeplayer3-arm/include/container.h @@ -0,0 +1,48 @@ +#ifndef CONTAINER_H_ +#define CONTAINER_H_ + +#include + +typedef enum +{ + CONTAINER_INIT, + CONTAINER_ADD, + CONTAINER_CAPABILITIES, + CONTAINER_PLAY, + CONTAINER_STOP, + CONTAINER_SEEK, + CONTAINER_SEEK_ABS, + CONTAINER_LENGTH, + CONTAINER_DEL, + CONTAINER_SWITCH_AUDIO, + CONTAINER_SWITCH_SUBTITLE, + CONTAINER_INFO, + CONTAINER_STATUS, + CONTAINER_LAST_PTS, + CONTAINER_DATA, + CONTAINER_SET_BUFFER_SEEK_TIME, + CONTAINER_SET_BUFFER_SIZE, + CONTAINER_GET_BUFFER_SIZE, + CONTAINER_GET_BUFFER_STATUS, + CONTAINER_STOP_BUFFER +} ContainerCmd_t; + +typedef struct Container_s +{ + char *Name; + int (* Command)(/*Context_t*/void *, ContainerCmd_t, void *); + char **Capabilities; + +} Container_t; + +extern Container_t FFMPEGContainer; + +typedef struct ContainerHandler_s +{ + char *Name; + Container_t *selectedContainer; + + int (* Command)(/*Context_t*/void *, ContainerCmd_t, void *); +} ContainerHandler_t; + +#endif diff --git a/libeplayer3-arm/include/debug.h b/libeplayer3-arm/include/debug.h new file mode 100644 index 0000000..9149895 --- /dev/null +++ b/libeplayer3-arm/include/debug.h @@ -0,0 +1,19 @@ +#ifndef debug_123 +#define debug_123 + +#include +#include + +static inline void Hexdump(unsigned char *Data, int length) +{ + int k; + for (k = 0; k < length; k++) + { + printf("%02x ", Data[k]); + if (((k + 1) & 31) == 0) + printf("\n"); + } + printf("\n"); +} + +#endif diff --git a/libeplayer3-arm/include/ffmpeg_metadata.h b/libeplayer3-arm/include/ffmpeg_metadata.h new file mode 100644 index 0000000..0a2a946 --- /dev/null +++ b/libeplayer3-arm/include/ffmpeg_metadata.h @@ -0,0 +1,45 @@ +#ifndef _ffmpeg_metadata_123 +#define _ffmpeg_metadata_123 + +/* these file contains a list of metadata tags which can be used by applications + * to stream specific information. it maps the tags to ffmpeg specific tags. + * + * fixme: if we add other container for some resons later (maybe some other libs + * support better demuxing or something like this), then we should think on a + * more generic mechanism! + */ + +/* metatdata map list: + */ +char *metadata_map[] = +{ + /* our tags ffmpeg tag / id3v2 */ + "Title", "TIT2", + "Title", "TT2", + "Artist", "TPE1", + "Artist", "TP1", + "AlbumArtist", "TPE2", + "AlbumArtist", "TP2", + "Album", "TALB", + "Album", "TAL", + "Year", "TDRL", /* fixme */ + "Year", "TDRC", /* fixme */ + "Comment", "unknown", + "Track", "TRCK", + "Track", "TRK", + "Copyright", "TCOP", + "Composer", "TCOM", + "Genre", "TCON", + "Genre", "TCO", + "EncodedBy", "TENC", + "EncodedBy", "TEN", + "Language", "TLAN", + "Performer", "TPE3", + "Performer", "TP3", + "Publisher", "TPUB", + "Encoder", "TSSE", + "Disc", "TPOS", + NULL +}; + +#endif diff --git a/libeplayer3-arm/include/manager.h b/libeplayer3-arm/include/manager.h new file mode 100644 index 0000000..cbca287 --- /dev/null +++ b/libeplayer3-arm/include/manager.h @@ -0,0 +1,109 @@ +#ifndef MANAGER_H_ +#define MANAGER_H_ + +#include +#include + +typedef enum +{ + MANAGER_ADD, + MANAGER_LIST, + MANAGER_GET, + MANAGER_GETNAME, + MANAGER_SET, + MANAGER_GETENCODING, + MANAGER_DEL, + MANAGER_GET_TRACK, + MANAGER_GET_TRACK_DESC, + MANAGER_INIT_UPDATE, + MANAGER_UPDATED_TRACK_INFO, + MANAGER_REGISTER_UPDATED_TRACK_INFO, +} ManagerCmd_t; + +typedef enum +{ + eTypeES, + eTypePES +} eTrackTypeEplayer; + +typedef struct Track_s +{ + char *Name; + char *Encoding; + int32_t Id; + int32_t AVIdx; + + /* new field for ffmpeg - add at the end so no problem + * can occur with not changed srt saa container + */ + char *language; + + /* length of track */ + int64_t duration; + uint32_t frame_rate; + uint32_t TimeScale; + int32_t version; + long long int pts; + long long int dts; + + /* for later use: */ + eTrackTypeEplayer type; + int width; + int height; + int32_t aspect_ratio_num; + int32_t aspect_ratio_den; + + /* stream from ffmpeg */ + void *stream; + /* AVCodecContext for steam */ + void *avCodecCtx; + /* codec extra data (header or some other stuff) */ + void *extraData; + int extraSize; + + uint8_t *aacbuf; + unsigned int aacbuflen; + int have_aacheader; + + /* If player2 or the elf do not support decoding of audio codec set this. + * AVCodec is than used for softdecoding and stream will be injected as PCM */ + int inject_as_pcm; + int inject_raw_pcm; + + int pending; +} Track_t; + +typedef struct TrackDescription_s +{ + int Id; + char *Name; + char *Encoding; + unsigned int frame_rate; + int width; + int height; + int32_t aspect_ratio_num; + int32_t aspect_ratio_den; + int progressive; + +} TrackDescription_t; + +typedef struct Manager_s +{ + char *Name; + int (* Command)(/*Context_t*/void *, ManagerCmd_t, void *); + char **Capabilities; + +} Manager_t; + +typedef struct ManagerHandler_s +{ + char *Name; + Manager_t *audio; + Manager_t *video; + Manager_t *subtitle; +} ManagerHandler_t; + +void freeTrack(Track_t *track); +void copyTrack(Track_t *to, Track_t *from); + +#endif diff --git a/libeplayer3-arm/include/misc.h b/libeplayer3-arm/include/misc.h new file mode 100644 index 0000000..55e98cb --- /dev/null +++ b/libeplayer3-arm/include/misc.h @@ -0,0 +1,112 @@ +#ifndef misc_123 +#define misc_123 + +#include +#include +#include +#include +#include + +/* some useful things needed by many files ... */ + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +typedef struct BitPacker_s +{ + uint8_t *Ptr; /* write pointer */ + uint32_t BitBuffer; /* bitreader shifter */ + int32_t Remaining; /* number of remaining in the shifter */ +} BitPacker_t; + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define INVALID_PTS_VALUE 0x200000000ull + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +void PutBits(BitPacker_t *ld, uint32_t code, uint32_t length); +void FlushBits(BitPacker_t *ld); +int8_t PlaybackDieNow(int8_t val); + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static inline char *getExtension(char *name) +{ + if (name) + { + char *ext = strrchr(name, '.'); + if (ext) + { + return ext + 1; + } + } + return NULL; +} + +/* the function returns the base name */ +static inline char *basename(char *name) +{ + int i = 0; + int pos = 0; + while (name[i] != 0) + { + if (name[i] == '/') + pos = i; + i++; + } + if (name[pos] == '/') + pos++; + return name + pos; +} + +/* the function returns the directry name */ +static inline char *dirname(char *name) +{ + static char path[100]; + uint32_t i = 0; + int32_t pos = 0; + while ((name[i] != 0) && (i < sizeof(path))) + { + if (name[i] == '/') + { + pos = i; + } + path[i] = name[i]; + i++; + } + path[i] = 0; + path[pos] = 0; + return path; +} + +static inline int32_t IsDreambox() +{ + struct stat buffer; + return (stat("/proc/stb/tpm/0/serial", &buffer) == 0); +} + +static inline uint32_t ReadUint32(uint8_t *buffer) +{ + uint32_t num = (uint32_t)buffer[0] << 24 | + (uint32_t)buffer[1] << 16 | + (uint32_t)buffer[2] << 8 | + (uint32_t)buffer[3]; + return num; +} + +static inline uint16_t ReadUInt16(uint8_t *buffer) +{ + uint16_t num = (uint16_t)buffer[0] << 8 | + (uint16_t)buffer[1]; + return num; +} + +#endif diff --git a/libeplayer3-arm/include/output.h b/libeplayer3-arm/include/output.h new file mode 100644 index 0000000..ccc0d62 --- /dev/null +++ b/libeplayer3-arm/include/output.h @@ -0,0 +1,88 @@ +#ifndef OUTPUT_H_ +#define OUTPUT_H_ + +#include + +typedef enum +{ + OUTPUT_INIT, + OUTPUT_ADD, + OUTPUT_DEL, + OUTPUT_CAPABILITIES, + OUTPUT_PLAY, + OUTPUT_STOP, + OUTPUT_PAUSE, + OUTPUT_OPEN, + OUTPUT_CLOSE, + OUTPUT_FLUSH, + OUTPUT_CONTINUE, + OUTPUT_FASTFORWARD, + OUTPUT_AVSYNC, + OUTPUT_CLEAR, + OUTPUT_PTS, + OUTPUT_SWITCH, + OUTPUT_SLOWMOTION, + OUTPUT_AUDIOMUTE, + OUTPUT_REVERSE, + OUTPUT_DISCONTINUITY_REVERSE, + OUTPUT_GET_FRAME_COUNT, + OUTPUT_GET_PROGRESSIVE, +} OutputCmd_t; + +typedef struct +{ + uint8_t *data; + uint32_t len; + + uint8_t *extradata; + uint32_t extralen; + + int64_t pts; + int64_t dts; + + uint32_t frameRate; + uint32_t timeScale; + + uint32_t width; + uint32_t height; + + uint32_t infoFlags; + + char *type; +} AudioVideoOut_t; + +typedef struct +{ + uint32_t trackId; + uint8_t *data; + uint32_t len; + + int64_t pts; + int64_t durationMS; // duration in miliseconds + + char *type; +} SubtitleOut_t; + + +typedef struct Output_s +{ + char *Name; + int32_t (* Command)(/*Context_t*/void *, OutputCmd_t, void *); + int32_t (* Write)(/*Context_t*/void *, void *privateData); + char **Capabilities; + +} Output_t; + +extern Output_t LinuxDvbOutput; +extern Output_t SubtitleOutput; + +typedef struct OutputHandler_s +{ + char *Name; + Output_t *audio; + Output_t *video; + Output_t *subtitle; + int32_t (* Command)(/*Context_t*/void *, OutputCmd_t, void *); +} OutputHandler_t; + +#endif diff --git a/libeplayer3-arm/include/pcm.h b/libeplayer3-arm/include/pcm.h new file mode 100644 index 0000000..96d98d7 --- /dev/null +++ b/libeplayer3-arm/include/pcm.h @@ -0,0 +1,36 @@ +/* + * pcm helper + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef pcm_h_ +#define pcm_h_ + +#include + +typedef struct pcmPrivateData_s +{ + uint8_t bResampling; + + /* Field taken direct from stream->codec */ + int32_t channels; + int32_t bits_per_coded_sample; + int32_t sample_rate; + int32_t bit_rate; + int32_t ffmpeg_codec_id; +} pcmPrivateData_t; +#endif diff --git a/libeplayer3-arm/include/pes.h b/libeplayer3-arm/include/pes.h new file mode 100644 index 0000000..1b2d019 --- /dev/null +++ b/libeplayer3-arm/include/pes.h @@ -0,0 +1,32 @@ +#ifndef pes_123 +#define pes_123 + +#define PES_MAX_HEADER_SIZE 64 +#define PES_PRIVATE_DATA_FLAG 0x80 +#define PES_PRIVATE_DATA_LENGTH 8 +#define PES_LENGTH_BYTE_0 5 +#define PES_LENGTH_BYTE_1 4 +#define PES_FLAGS_BYTE 7 +#define PES_EXTENSION_DATA_PRESENT 0x01 +#define PES_HEADER_DATA_LENGTH_BYTE 8 +#define PES_START_CODE_RESERVED_4 0xfd +#define PES_VERSION_FAKE_START_CODE 0x31 + + +#define MAX_PES_PACKET_SIZE (65535) + + +/* start codes */ +#define PCM_PES_START_CODE 0xbd +#define PRIVATE_STREAM_1_PES_START_CODE 0xbd +#define H263_VIDEO_PES_START_CODE 0xfe +#define H264_VIDEO_PES_START_CODE 0xe2 +#define MPEG_VIDEO_PES_START_CODE 0xe0 +#define MPEG_AUDIO_PES_START_CODE 0xc0 +#define VC1_VIDEO_PES_START_CODE 0xfd +#define AAC_AUDIO_PES_START_CODE 0xcf + +int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t pts, int32_t pic_start_code); +int32_t InsertVideoPrivateDataHeader(uint8_t *data, int32_t payload_size); + +#endif diff --git a/libeplayer3-arm/include/playback.h b/libeplayer3-arm/include/playback.h new file mode 100644 index 0000000..3664173 --- /dev/null +++ b/libeplayer3-arm/include/playback.h @@ -0,0 +1,41 @@ +#ifndef PLAYBACK_H_ +#define PLAYBACK_H_ +#include +#include + +typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_SEEK_ABS, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT} PlaybackCmd_t; + +typedef struct PlaybackHandler_s +{ + char *Name; + + int32_t fd; + + uint8_t isFile; + uint8_t isHttp; + + uint8_t isPlaying; + uint8_t isPaused; + uint8_t isForwarding; + uint8_t isSeeking; + uint8_t isCreationPhase; + + int32_t BackWard; + int32_t SlowMotion; + int32_t Speed; + int32_t AVSync; + + uint8_t isVideo; + uint8_t isAudio; + uint8_t isSubtitle; + uint8_t abortRequested; + + int32_t (* Command)(/*Context_t*/void *, PlaybackCmd_t, void *); + char *uri; + off_t size; + uint8_t noprobe; /* hack: only minimal probing in av_find_stream_info */ + uint8_t isLoopMode; + uint8_t isTSLiveMode; +} PlaybackHandler_t; + +#endif diff --git a/libeplayer3-arm/include/stm_ioctls.h b/libeplayer3-arm/include/stm_ioctls.h new file mode 100644 index 0000000..fcb19ee --- /dev/null +++ b/libeplayer3-arm/include/stm_ioctls.h @@ -0,0 +1,335 @@ +/* + * stm_ioctls.h + * + * Copyright (C) STMicroelectronics Limited 2005. All rights reserved. + * + * Extensions to the LinuxDVB API (v3) implemented by the Havana implemenation. + */ + +#ifndef H_STM_IOCTLS +#define H_STM_IOCTLS + +/* + * Whenever a sequence of values is extended (define or enum) always add the new values + * So that old values are unchange to maintain binary compatibility. + */ + +#define DVB_SPEED_NORMAL_PLAY 1000 +#define DVB_SPEED_STOPPED 0 +#define DVB_SPEED_REVERSE_STOPPED 0x80000000 +#define DVB_FRAME_RATE_MULTIPLIER 1000 + +#define VIDEO_FULL_SCREEN (VIDEO_CENTER_CUT_OUT+1) + +#define DMX_FILTER_BY_PRIORITY_LOW 0x00010000 /* These flags tell the transport pes filter whether to filter */ +#define DMX_FILTER_BY_PRIORITY_HIGH 0x00020000 /* using the ts priority bit and, if so, whether to filter on */ +#define DMX_FILTER_BY_PRIORITY_MASK 0x00030000 /* bit set or bit clear */ + +/* + * Extra events + */ + +#define VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY 5 /*(VIDEO_EVENT_VSYNC+1)*/ +#define VIDEO_EVENT_FRAME_DECODED_LATE (VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY+1) +#define VIDEO_EVENT_DATA_DELIVERED_LATE (VIDEO_EVENT_FRAME_DECODED_LATE+1) +#define VIDEO_EVENT_STREAM_UNPLAYABLE (VIDEO_EVENT_DATA_DELIVERED_LATE+1) +#define VIDEO_EVENT_TRICK_MODE_CHANGE (VIDEO_EVENT_STREAM_UNPLAYABLE+1) +#define VIDEO_EVENT_VSYNC_OFFSET_MEASURED (VIDEO_EVENT_TRICK_MODE_CHANGE+1) +#define VIDEO_EVENT_FATAL_ERROR (VIDEO_EVENT_VSYNC_OFFSET_MEASURED+1) +#define VIDEO_EVENT_OUTPUT_SIZE_CHANGED (VIDEO_EVENT_FATAL_ERROR+1) +#define VIDEO_EVENT_FATAL_HARDWARE_FAILURE (VIDEO_EVENT_OUTPUT_SIZE_CHANGED+1) + +/* + * List of possible container types - used to select demux.. If stream_source is VIDEO_SOURCE_DEMUX + * then default is TRANSPORT, if stream_source is VIDEO_SOURCE_MEMORY then default is PES + */ +typedef enum +{ + STREAM_TYPE_NONE, /* Deprecated */ + STREAM_TYPE_TRANSPORT,/* Use latest PTI driver so it can be Deprecated */ + STREAM_TYPE_PES, + STREAM_TYPE_ES, /* Deprecated */ + STREAM_TYPE_PROGRAM, /* Deprecated */ + STREAM_TYPE_SYSTEM, /* Deprecated */ + STREAM_TYPE_SPU, /* Deprecated */ + STREAM_TYPE_NAVI, /* Deprecated */ + STREAM_TYPE_CSS, /* Deprecated */ + STREAM_TYPE_AVI, /* Deprecated */ + STREAM_TYPE_MP3, /* Deprecated */ + STREAM_TYPE_H264, /* Deprecated */ + STREAM_TYPE_ASF, /* Needs work so it can be deprecated */ + STREAM_TYPE_MP4, /* Deprecated */ + STREAM_TYPE_RAW /* Deprecated */ +} stream_type_t; + +/* + * List of possible video encodings - used to select frame parser and codec. + */ +typedef enum +{ + VIDEO_ENCODING_AUTO, + VIDEO_ENCODING_MPEG1, + VIDEO_ENCODING_MPEG2, + VIDEO_ENCODING_MJPEG, + VIDEO_ENCODING_DIVX3, + VIDEO_ENCODING_DIVX4, + VIDEO_ENCODING_DIVX5, + VIDEO_ENCODING_MPEG4P2, + VIDEO_ENCODING_H264, + VIDEO_ENCODING_WMV, + VIDEO_ENCODING_VC1, + VIDEO_ENCODING_RAW, + VIDEO_ENCODING_H263, + VIDEO_ENCODING_FLV1, + VIDEO_ENCODING_VP6, + VIDEO_ENCODING_RMV, + VIDEO_ENCODING_DIVXHD, + VIDEO_ENCODING_AVS, + VIDEO_ENCODING_VP3, + VIDEO_ENCODING_THEORA, + VIDEO_ENCODING_COMPOCAP, + VIDEO_ENCODING_NONE, + VIDEO_ENCODING_PRIVATE +} video_encoding_t; + + +/* + * List of possible audio encodings - used to select frame parser and codec. + */ +typedef enum +{ + AUDIO_ENCODING_AUTO, + AUDIO_ENCODING_PCM, + AUDIO_ENCODING_LPCM, + AUDIO_ENCODING_MPEG1, + AUDIO_ENCODING_MPEG2, + AUDIO_ENCODING_MP3, + AUDIO_ENCODING_AC3, + AUDIO_ENCODING_DTS, + AUDIO_ENCODING_AAC, + AUDIO_ENCODING_WMA, + AUDIO_ENCODING_RAW, + AUDIO_ENCODING_LPCMA, + AUDIO_ENCODING_LPCMH, + AUDIO_ENCODING_LPCMB, + AUDIO_ENCODING_SPDIF, /* +#include +#include + +typedef enum { eNone, eAudio, eVideo} eWriterType_t; + +typedef struct +{ + int fd; + unsigned char *data; + unsigned int len; + unsigned long long int Pts; + unsigned long long int Dts; + unsigned char *private_data; + unsigned int private_size; + unsigned int FrameRate; + unsigned int FrameScale; + unsigned int Width; + unsigned int Height; + unsigned char Version; + unsigned int InfoFlags; +} WriterAVCallData_t; + + + +typedef struct WriterCaps_s +{ + char *name; + eWriterType_t type; + char *textEncoding; + /* fixme: revise if this is an enum! */ + int dvbEncoding; /* For sh4 */ + int dvbStreamType; /* For mipsel */ + int dvbCodecType; /* For mipsel */ +} WriterCaps_t; + +typedef struct Writer_s +{ + int (* reset)(); + int (* writeData)(void *); + int (* writeReverseData)(void *); + WriterCaps_t *caps; +} Writer_t; + +extern Writer_t WriterAudioLPCM; +extern Writer_t WriterAudioIPCM; +extern Writer_t WriterAudioPCM; +extern Writer_t WriterAudioMP3; +extern Writer_t WriterAudioMPEGL3; +extern Writer_t WriterAudioAC3; +extern Writer_t WriterAudioEAC3; +extern Writer_t WriterAudioAAC; +extern Writer_t WriterAudioAACLATM; +extern Writer_t WriterAudioAACPLUS; +extern Writer_t WriterAudioDTS; +extern Writer_t WriterAudioWMA; +extern Writer_t WriterAudioWMAPRO; +extern Writer_t WriterAudioFLAC; +extern Writer_t WriterAudioVORBIS; +extern Writer_t WriterAudioAMR; + +extern Writer_t WriterVideoMPEG1; +extern Writer_t WriterVideoMPEG2; +extern Writer_t WriterVideoMPEG4; +extern Writer_t WriterVideoMPEGH264; +extern Writer_t WriterVideoH264; +extern Writer_t WriterVideoDIVX3; +extern Writer_t WriterVideoWMV; +extern Writer_t WriterVideoDIVX; +extern Writer_t WriterVideoFOURCC; +extern Writer_t WriterVideoMSCOMP; +extern Writer_t WriterVideoH263; +extern Writer_t WriterVideoH265; +extern Writer_t WriterVideoFLV; +extern Writer_t WriterVideoVC1; +extern Writer_t WriterVideoVP6; +extern Writer_t WriterVideoVP8; +extern Writer_t WriterVideoVP9; +extern Writer_t WriterVideoSPARK; +extern Writer_t WriterFramebuffer; +extern Writer_t WriterPipe; + +Writer_t *getWriter(char *encoding); + +Writer_t *getDefaultVideoWriter(); +Writer_t *getDefaultAudioWriter(); +ssize_t write_with_retry(int fd, const void *buf, size_t size); +ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic); +#endif diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c new file mode 100644 index 0000000..04af426 --- /dev/null +++ b/libeplayer3-arm/main/exteplayer.c @@ -0,0 +1,843 @@ +/* + * eplayer3: command line playback using libeplayer3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "misc.h" + +#define DUMP_BOOL(x) 0 == x ? "false" : "true" +#define IPTV_MAX_FILE_PATH 1024 + +extern int ffmpeg_av_dict_set(const char *key, const char *value, int flags); +extern void aac_software_decoder_set(const int32_t val); +extern void aac_latm_software_decoder_set(const int32_t val); +extern void dts_software_decoder_set(const int32_t val); +extern void wma_software_decoder_set(const int32_t val); +extern void ac3_software_decoder_set(const int32_t val); +extern void eac3_software_decoder_set(const int32_t val); +extern void mp3_software_decoder_set(const int32_t val); +extern void rtmp_proto_impl_set(const int32_t val); +extern void flv2mpeg4_converter_set(const int32_t val); +extern void sel_program_id_set(const int32_t val); + +extern void pcm_resampling_set(int32_t val); +extern void stereo_software_decoder_set(int32_t val); +extern void insert_pcm_as_lpcm_set(int32_t val); +extern void progressive_playback_set(int32_t val); + +extern OutputHandler_t OutputHandler; +extern PlaybackHandler_t PlaybackHandler; +extern ContainerHandler_t ContainerHandler; +extern ManagerHandler_t ManagerHandler; + +static Context_t *g_player = NULL; + +static void TerminateAllSockets(void) +{ + int i; + for (i = 0; i < 1024; ++i) + { + if (0 == shutdown(i, SHUT_RDWR)) + { + /* yes, I know that this is not good practice and I know what this could cause + * but in this use case it can be accepted. + * We must close socket because without closing it recv will return 0 (after shutdown) + * 0 is not correctly handled by external libraries + */ + close(i); + } + } +} + +static int g_pfd[2] = {-1, -1}; /* Used to wake terminate thread */ +static int isPlaybackStarted = 0; +static pthread_mutex_t playbackStartMtx; + +static void *TermThreadFun(void *arg) +{ + const char *socket_path = "/tmp/iptvplayer_extplayer_term_fd"; + struct sockaddr_un addr; + int fd = -1; + int cl = -1; + int nfds = 1; + fd_set readfds; + unlink(socket_path); + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + { + perror("TermThreadFun socket error"); + goto finish; + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + { + perror("TermThreadFun bind error"); + goto finish; + } + if (listen(fd, 1) == -1) + { + perror("TermThreadFun listen error"); + goto finish; + } + FD_ZERO(&readfds); + FD_SET(g_pfd[0], &readfds); + FD_SET(fd, &readfds); + nfds = fd > g_pfd[0] ? fd + 1 : g_pfd[0] + 1; + while (select(nfds, &readfds, NULL, NULL, NULL) == -1 + && errno == EINTR) + { + /* Restart if interrupted by signal */ + continue; + } + if (FD_ISSET(fd, &readfds)) + { + /* + if ( (cl = accept(fd, NULL, NULL)) == -1) + { + perror("TermThreadFun accept error"); + goto finish; + } + */ + pthread_mutex_lock(&playbackStartMtx); + PlaybackDieNow(1); + if (isPlaybackStarted) + TerminateAllSockets(); + else + kill(getpid(), SIGINT); + pthread_mutex_unlock(&playbackStartMtx); + } +finish: + close(cl); + close(fd); + pthread_exit(NULL); +} + +static void map_inter_file_path(char *filename) +{ + if (0 == strncmp(filename, "iptv://", 7)) + { + FILE *f = fopen(filename + 7, "r"); + if (NULL != f) + { + size_t num = fread(filename, 1, IPTV_MAX_FILE_PATH - 1, f); + fclose(f); + if (num > 0 && filename[num - 1] == '\n') + { + filename[num - 1] = '\0'; + } + else + { + filename[num] = '\0'; + } + } + } +} + +static int kbhit(void) +{ + struct timeval tv; + fd_set read_fd; + tv.tv_sec = 1; + tv.tv_usec = 0; + FD_ZERO(&read_fd); + FD_SET(0, &read_fd); + if (-1 == select(1, &read_fd, NULL, NULL, &tv)) + { + return 0; + } + if (FD_ISSET(0, &read_fd)) + { + return 1; + } + return 0; +} + +static void SetBuffering() +{ + static char buff[2048]; + memset(buff, '\0', sizeof(buff)); + if (setvbuf(stderr, buff, _IOLBF, sizeof(buff))) + { + printf("SetBuffering: failed to change the buffer of stderr\n"); + } + // make fgets not blocking + int flags = fcntl(stdin->_fileno, F_GETFL, 0); + fcntl(stdin->_fileno, F_SETFL, flags | O_NONBLOCK); +} + +static void SetNice(int prio) +{ +#if 0 + setpriority(PRIO_PROCESS, 0, -8); + int prio = sched_get_priority_max(SCHED_RR) / 2; + struct sched_param param = + { + .sched_priority = prio + }; + sched_setscheduler(0, SCHED_RR, ¶m); +#else + int prevPrio = getpriority(PRIO_PROCESS, 0); + if (-1 == setpriority(PRIO_PROCESS, 0, prio)) + { + printf("setpriority - failed\n"); + } +#endif +} + +static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbackSwitchCmd, const char *argvBuff) +{ + int commandRetVal = 0; + if (NULL == ptrManager || NULL == argvBuff || 2 != strnlen(argvBuff, 2)) + { + return -1; + } + switch (argvBuff[1]) + { + case 'l': + { + TrackDescription_t *TrackList = NULL; + ptrManager->Command(g_player, MANAGER_LIST, &TrackList); + if (NULL != TrackList) + { + int i = 0; + fprintf(stderr, "{\"%c_%c\": [", argvBuff[0], argvBuff[1]); + for (i = 0; TrackList[i].Id >= 0; ++i) + { + if (0 < i) + { + fprintf(stderr, ", "); + } + fprintf(stderr, "{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}", TrackList[i].Id, TrackList[i].Encoding, TrackList[i].Name); + free(TrackList[i].Encoding); + free(TrackList[i].Name); + } + fprintf(stderr, "]}\n"); + free(TrackList); + } + else + { + // not tracks + fprintf(stderr, "{\"%c_%c\": []}\n", argvBuff[0], argvBuff[1]); + } + break; + } + case 'c': + { + TrackDescription_t *track = NULL; + ptrManager->Command(g_player, MANAGER_GET_TRACK_DESC, &track); + if (NULL != track) + { + if ('a' == argvBuff[0] || 's' == argvBuff[0]) + { + fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}}\n", argvBuff[0], argvBuff[1], track->Id, track->Encoding, track->Name); + } + else // video + { + fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\",\"w\":%d,\"h\":%d,\"f\":%u,\"p\":%d,\"an\":%d,\"ad\":%d}}\n", \ + argvBuff[0], argvBuff[1], track->Id, track->Encoding, track->Name, track->width, track->height, track->frame_rate, track->progressive, track->aspect_ratio_num, track->aspect_ratio_den); + } + free(track->Encoding); + free(track->Name); + free(track); + } + else + { + // no tracks + if ('a' == argvBuff[0] || 's' == argvBuff[0]) + { + fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}}\n", argvBuff[0], argvBuff[1], -1, "", ""); + } + else // video + { + fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\",\"w\":%d,\"h\":%d,\"f\":%u,\"p\":%d}}\n", argvBuff[0], argvBuff[1], -1, "", "", -1, -1, 0, -1); + } + } + break; + } + default: + { + /* switch command available only for audio and subtitle tracks */ + if ('a' == argvBuff[0] || 's' == argvBuff[0]) + { + int ok = 0; + int id = -1; + if ('i' == argvBuff[1]) + { + int idx = -1; + ok = sscanf(argvBuff + 2, "%d", &idx); + if (idx >= 0) + { + TrackDescription_t *TrackList = NULL; + ptrManager->Command(g_player, MANAGER_LIST, &TrackList); + if (NULL != TrackList) + { + int i = 0; + for (i = 0; TrackList[i].Id >= 0; ++i) + { + if (idx == i) + { + id = TrackList[i].Id; + } + free(TrackList[i].Encoding); + free(TrackList[i].Name); + } + free(TrackList); + } + } + else + { + id = idx; + } + } + else + { + ok = sscanf(argvBuff + 1, "%d", &id); + } + if (id >= 0 || (1 == ok && id == -1)) + { + commandRetVal = g_player->playback->Command(g_player, playbackSwitchCmd, (void *)&id); + fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"sts\":%d}}\n", argvBuff[0], 's', id, commandRetVal); + } + } + break; + } + } + return commandRetVal; +} + +static void UpdateVideoTrack() +{ + HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc"); +} + +static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int *pAudioTrackIdx, int *subtitleTrackIdx) +{ + int ret = 0; + int c; + int digit_optind = 0; + int aopt = 0, bopt = 0; + char *copt = 0, *dopt = 0; + while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:")) != -1) + { + switch (c) + { + case 'a': + { + int flag = atoi(optarg); + printf("Software decoder will be used for AAC codec\n"); + aac_software_decoder_set(flag & 0x01); + aac_latm_software_decoder_set(flag & 0x02); + break; + } + case 'e': + printf("Software decoder will be used for EAC3 codec\n"); + eac3_software_decoder_set(1); + break; + case '3': + printf("Software decoder will be used for AC3 codec\n"); + ac3_software_decoder_set(1); + break; + case 'd': + printf("Software decoder will be used for DTS codec\n"); + dts_software_decoder_set(1); + break; + case 'm': + printf("Software decoder will be used for MP3 codec\n"); + mp3_software_decoder_set(1); + break; + case 'w': + printf("Software decoder will be used for WMA codec\n"); + wma_software_decoder_set(1); + break; + case 'l': + printf("Audio software decoding as LPCM\n"); + insert_pcm_as_lpcm_set(1); + break; + case 's': + printf("Software decoder will decode to stereo\n"); + stereo_software_decoder_set(1); + break; + case 'r': + printf("Software decoder do not use PCM resampling\n"); + pcm_resampling_set(0); + break; + case 'o': + printf("Set progressive download to %d\n", atoi(optarg)); + progressive_playback_set(atoi(optarg)); + break; + case 'p': + SetNice(atoi(optarg)); + break; + case 'P': + sel_program_id_set(atoi(optarg)); + break; + case 't': + *pAudioTrackIdx = atoi(optarg); + break; + case '9': + *subtitleTrackIdx = atoi(optarg); + break; + case 'x': + strncpy(audioFile, optarg, IPTV_MAX_FILE_PATH - 1); + map_inter_file_path(audioFile); + break; + case 'h': + ffmpeg_av_dict_set("headers", optarg, 0); + break; + case 'u': + ffmpeg_av_dict_set("user-agent", optarg, 0); + break; + case 'c': + printf("For now cookies should be set via headers option!\n"); + ffmpeg_av_dict_set("cookies", optarg, 0); + break; + case 'i': + printf("Play in (infinity) loop.\n"); + PlaybackHandler.isLoopMode = 1; + break; + case 'v': + printf("Use live TS stream mode.\n"); + PlaybackHandler.isTSLiveMode = 1; + break; + case 'n': + printf("Force rtmp protocol implementation\n"); + rtmp_proto_impl_set(atoi(optarg)); + break; + case '0': + ffmpeg_av_dict_set("video_rep_index", optarg, 0); + break; + case '1': + ffmpeg_av_dict_set("audio_rep_index", optarg, 0); + break; + case '4': +#ifdef HAVE_FLV2MPEG4_CONVERTER + flv2mpeg4_converter_set(atoi(optarg)); +#endif + break; + case 'f': + { + char *ffopt = strdup(optarg); + char *ffval = strchr(ffopt, '='); + if (ffval) + { + *ffval = '\0'; + ffval += 1; + ffmpeg_av_dict_set(ffopt, ffval, 0); + } + free(ffopt); + break; + } + default: + printf("?? getopt returned character code 0%o ??\n", c); + ret = -1; + } + } + if (0 == ret && optind < argc) + { + ret = 0; + if (NULL == strstr(argv[optind], "://")) + { + strcpy(file, "file://"); + } + strcat(file, argv[optind]); + map_inter_file_path(file); + printf("file: [%s]\n", file); + ++optind; + } + else + { + ret = -1; + } + return ret; +} + +int main(int argc, char *argv[]) +{ + pthread_t termThread; + int isTermThreadStarted = 0; + char file[IPTV_MAX_FILE_PATH]; + memset(file, '\0', sizeof(file)); + char audioFile[IPTV_MAX_FILE_PATH]; + memset(audioFile, '\0', sizeof(audioFile)); + int audioTrackIdx = -1; + int subtitleTrackIdx = -1; + char argvBuff[256]; + memset(argvBuff, '\0', sizeof(argvBuff)); + int commandRetVal = -1; + /* inform client that we can handle additional commands */ + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 36); + if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx)) + { + printf("Usage: exteplayer3 filePath [-u user-agent] [-c cookies] [-h headers] [-p prio] [-a] [-d] [-w] [-l] [-s] [-i] [-t audioTrackId] [-9 subtitleTrackId] [-x separateAudioUri] plabackUri\n"); + printf("[-a 0|1|2|3] AAC software decoding - 1 bit - AAC ADTS, 2 - bit AAC LATM\n"); + printf("[-e] EAC3 software decoding\n"); + printf("[-3] AC3 software decoding\n"); + printf("[-d] DTS software decoding\n"); + printf("[-m] MP3 software decoding\n"); + printf("[-w] WMA1, WMA2, WMA/PRO software decoding\n"); + printf("[-l] software decoder use LPCM for injection (otherwise wav PCM will be used)\n"); + printf("[-s] software decoding as stereo [downmix]\n"); +#ifdef HAVE_FLV2MPEG4_CONVERTER + printf("[-4 0|1] - disable/enable flv2mpeg4 converter\n"); +#endif + printf("[-i] play in infinity loop\n"); + printf("[-v] switch to live TS stream mode\n"); + printf("[-n 0|1|2] rtmp force protocol implementation auto(0) native/ffmpeg(1) or librtmp(2)\n"); + printf("[-o 0|1] set progressive download\n"); + printf("[-p value] nice value\n"); + printf("[-P value] select Program ID from multi-service stream\n"); + printf("[-t id] audio track ID switched on at start\n"); + printf("[-9 id] subtitle track ID switched on at start\n"); + printf("[-h headers] set custom HTTP headers \"Name: value\\r\\nName: value\\r\\n\"\n"); + printf("[-u user-agent] set custom http User-Agent header\n"); + printf("[-c cookies] set cookies - not working at now, please use -h instead\n"); + printf("[-x separateAudioUri]\n"); + printf("[-0 idx] video MPEG-DASH representation index\n"); + printf("[-1 idx] audio MPEG-DASH representation index\n"); + printf("[-f ffopt=ffval] any other ffmpeg option\n"); + exit(1); + } + g_player = malloc(sizeof(Context_t)); + if (NULL == g_player) + { + printf("g_player allocate error\n"); + exit(1); + } + pthread_mutex_init(&playbackStartMtx, NULL); + do + { + int flags = 0; + if (pipe(g_pfd) == -1) + break; + /* Make read and write ends of pipe nonblocking */ + if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1) + break; + /* Make read end nonblocking */ + flags |= O_NONBLOCK; + if (fcntl(g_pfd[0], F_SETFL, flags) == -1) + break; + if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1) + break; + /* Make write end nonblocking */ + flags |= O_NONBLOCK; + if (fcntl(g_pfd[1], F_SETFL, flags) == -1) + break; + if (0 == pthread_create(&termThread, NULL, TermThreadFun, NULL)) + isTermThreadStarted = 1; + } + while (0); + g_player->playback = &PlaybackHandler; + g_player->output = &OutputHandler; + g_player->container = &ContainerHandler; + g_player->manager = &ManagerHandler; + // make sure to kill myself when parent dies + prctl(PR_SET_PDEATHSIG, SIGKILL); + SetBuffering(); + //Registrating output devices + g_player->output->Command(g_player, OUTPUT_ADD, "audio"); + g_player->output->Command(g_player, OUTPUT_ADD, "video"); + g_player->output->Command(g_player, OUTPUT_ADD, "subtitle"); + g_player->manager->video->Command(g_player, MANAGER_REGISTER_UPDATED_TRACK_INFO, UpdateVideoTrack); + if (strncmp(file, "rtmp", 4) && strncmp(file, "ffrtmp", 4)) + { + g_player->playback->noprobe = 1; + } + PlayFiles_t playbackFiles = {file, NULL}; + if ('\0' != audioFile[0]) + { + playbackFiles.szSecondFile = audioFile; + } + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_OPEN, &playbackFiles); + fprintf(stderr, "{\"PLAYBACK_OPEN\":{\"OutputName\":\"%s\", \"file\":\"%s\", \"sts\":%d}}\n", g_player->output->Name, file, commandRetVal); + if (commandRetVal < 0) + { + if (NULL != g_player) + { + free(g_player); + } + return 10; + } + { + pthread_mutex_lock(&playbackStartMtx); + isPlaybackStarted = 1; + pthread_mutex_unlock(&playbackStartMtx); + commandRetVal = g_player->output->Command(g_player, OUTPUT_OPEN, NULL); + fprintf(stderr, "{\"OUTPUT_OPEN\":{\"sts\":%d}}\n", commandRetVal); + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PLAY, NULL); + fprintf(stderr, "{\"PLAYBACK_PLAY\":{\"sts\":%d}}\n", commandRetVal); + if (g_player->playback->isPlaying) + { + HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc"); + HandleTracks(g_player->manager->audio, (PlaybackCmd_t) - 1, "al"); + if (audioTrackIdx >= 0) + { + static char cmd[128] = ""; // static to not allocate on stack + sprintf(cmd, "ai%d\n", audioTrackIdx); + commandRetVal = HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, cmd); + } + HandleTracks(g_player->manager->audio, (PlaybackCmd_t) - 1, "ac"); + HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sl"); + if (subtitleTrackIdx >= 0) + { + static char cmd[128] = ""; // static to not allocate on stack + sprintf(cmd, "si%d\n", subtitleTrackIdx); + commandRetVal = HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, cmd); + } + HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sc"); + } + while (g_player->playback->isPlaying) + { + /* we made fgets non blocking */ + if (NULL == fgets(argvBuff, sizeof(argvBuff) - 1, stdin)) + { + /* wait for data - max 1s */ + kbhit(); + continue; + } + if (0 == argvBuff[0]) + { + continue; + } + switch (argvBuff[0]) + { + case 'v': + { + HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, argvBuff); + break; + } + case 'a': + { + HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, argvBuff); + break; + } + case 's': + { + HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, argvBuff); + break; + } + case 'q': + { + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_STOP, NULL); + fprintf(stderr, "{\"PLAYBACK_STOP\":{\"sts\":%d}}\n", commandRetVal); + break; + } + case 'c': + { + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_CONTINUE, NULL); + fprintf(stderr, "{\"PLAYBACK_CONTINUE\":{\"sts\":%d}}\n", commandRetVal); + break; + } + case 'p': + { + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PAUSE, NULL); + fprintf(stderr, "{\"PLAYBACK_PAUSE\":{\"sts\":%d}}\n", commandRetVal); + break; + } + case 'm': + { + int speed = 0; + sscanf(argvBuff + 1, "%d", &speed); + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SLOWMOTION, &speed); + fprintf(stderr, "{\"PLAYBACK_SLOWMOTION\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal); + break; + } + case 'o': + { + int flags = 0; + if (1 == sscanf(argvBuff + 1, "%d", &flags)) + { + progressive_playback_set(flags); + fprintf(stderr, "{\"PROGRESSIVE_DOWNLOAD\":{\"flags\":%d, \"sts\":0}}\n", flags); + } + break; + } + case 'f': + { + int speed = 0; + sscanf(argvBuff + 1, "%d", &speed); + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTFORWARD, &speed); + fprintf(stderr, "{\"PLAYBACK_FASTFORWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal); + break; + } + case 'b': + { + int speed = 0; + sscanf(argvBuff + 1, "%d", &speed); + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTBACKWARD, &speed); + fprintf(stderr, "{\"PLAYBACK_FASTBACKWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal); + break; + } + case 'g': + { + int32_t gotoPos = 0; + int64_t length = 0; + int32_t lengthInt = 0; + int64_t sec = 0; + int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check + sscanf(argvBuff + 2, "%d", &gotoPos); + if (0 <= gotoPos || force) + { + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void *)&length); + fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal); + lengthInt = (int32_t)length; + if (10 <= lengthInt || force) + { + sec = gotoPos; + if (!force && gotoPos >= lengthInt) + { + sec = lengthInt - 10; + } + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK_ABS, (void *)&sec); + fprintf(stderr, "{\"PLAYBACK_SEEK_ABS\":{\"sec\":%lld, \"sts\":%d}}\n", sec, commandRetVal); + } + } + break; + } + case 'k': + { + int32_t seek = 0; + int64_t length = 0; + int32_t lengthInt = 0; + int64_t sec = 0; + int64_t pts = 0; + int32_t CurrentSec = 0; + int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check + sscanf(argvBuff + 2, "%d", &seek); + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts); + CurrentSec = (int32_t)(pts / 90000); + if (0 == commandRetVal) + { + fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90, commandRetVal); + } + if (0 == commandRetVal || force) + { + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void *)&length); + fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal); + lengthInt = (int32_t)length; + if (10 <= lengthInt || force) + { + int32_t ergSec = CurrentSec + seek; + if (!force && 0 > ergSec) + { + sec = CurrentSec * -1; // jump to start position + } + else if (!force && ergSec >= lengthInt) + { + sec = (lengthInt - CurrentSec) - 5; + if (0 < sec) + { + sec = 0; // no jump we are at the end + } + } + else + { + sec = seek; + } + } + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK, (void *)&sec); + fprintf(stderr, "{\"PLAYBACK_SEEK\":{\"sec\":%lld, \"sts\":%d}}\n", sec, commandRetVal); + } + break; + } + case 'l': + { + int64_t length = 0; + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void *)&length); + fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal); + break; + } + case 'j': + { + int64_t pts = 0; + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts); + if (0 == commandRetVal) + { + fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90, commandRetVal); + } + break; + } + case 'i': + { + PlaybackHandler_t *ptrP = g_player->playback; + if (ptrP) + { + fprintf(stderr, "{\"PLAYBACK_INFO\":{ \"isPlaying\":%s, \"isPaused\":%s, \"isForwarding\":%s, \"isSeeking\":%s, \"isCreationPhase\":%s,", \ + DUMP_BOOL(ptrP->isPlaying), DUMP_BOOL(ptrP->isPaused), DUMP_BOOL(ptrP->isForwarding), DUMP_BOOL(ptrP->isSeeking), DUMP_BOOL(ptrP->isCreationPhase)); + fprintf(stderr, "\"BackWard\":%d, \"SlowMotion\":%d, \"Speed\":%d, \"AVSync\":%d,", ptrP->BackWard, ptrP->SlowMotion, ptrP->Speed, ptrP->AVSync); + fprintf(stderr, " \"isVideo\":%s, \"isAudio\":%s, \"isSubtitle\":%s, \"isDvbSubtitle\":%s, \"isTeletext\":%s, \"mayWriteToFramebuffer\":%s, \"abortRequested\":%s }}\n", \ + DUMP_BOOL(ptrP->isVideo), DUMP_BOOL(ptrP->isAudio), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(ptrP->abortRequested)); + } + break; + } + case 'n': + { + uint8_t loop = 0; + if ('1' == argvBuff[1] || '0' == argvBuff[1]) + { + PlaybackHandler_t *ptrP = g_player->playback; + if (ptrP) + { + ptrP->isLoopMode = '1' == argvBuff[1] ? 1 : 0; + fprintf(stderr, "{\"N\":{ \"isLoop\":%s }}\n", DUMP_BOOL(ptrP->isLoopMode)); + } + } + break; + } + default: + { + break; + } + } + } + g_player->output->Command(g_player, OUTPUT_CLOSE, NULL); + } + if (NULL != g_player) + { + free(g_player); + } + if (isTermThreadStarted && 1 == write(g_pfd[1], "x", 1)) + { + pthread_join(termThread, NULL); + } + pthread_mutex_destroy(&playbackStartMtx); + close(g_pfd[0]); + close(g_pfd[1]); + //printOutputCapabilities(); + exit(0); +} diff --git a/libeplayer3-arm/manager/audio.c b/libeplayer3-arm/manager/audio.c new file mode 100644 index 0000000..a0ee8f2 --- /dev/null +++ b/libeplayer3-arm/manager/audio.c @@ -0,0 +1,323 @@ +/* + * audio manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include +#include "manager.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define TRACKWRAP 20 + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define AUDIO_MGR_DEBUG +#else +#define AUDIO_MGR_SILENT +#endif + +#ifdef AUDIO_MGR_DEBUG + +static short debug_level = 40; + +#define audio_mgr_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] \n" fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define audio_mgr_printf(level, x...) +#endif + +#ifndef AUDIO_MGR_SILENT +#define audio_mgr_err(x...) do { printf(x); } while (0) +#else +#define audio_mgr_err(x...) +#endif + +/* Error Constants */ +#define cERR_AUDIO_MGR_NO_ERROR 0 +#define cERR_AUDIO_MGR_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Track_t *Tracks = NULL; +static int TrackCount = 0; +static int CurrentTrack = 0; //TRACK[0] as default. + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int ManagerAdd(Context_t *context, Track_t track) +{ + audio_mgr_printf(10, "%s::%s name=\"%s\" encoding=\"%s\" id=%d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id); + if (Tracks == NULL) + { + Tracks = malloc(sizeof(Track_t) * TRACKWRAP); + int i; + for (i = 0; i < TRACKWRAP; i++) + { + Tracks[i].Id = -1; + } + } + if (Tracks == NULL) + { + audio_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return cERR_AUDIO_MGR_ERROR; + } + int i = 0; + for (i = 0; i < TRACKWRAP; i++) + { + if (Tracks[i].Id == track.Id) + { + Tracks[i].pending = 0; + return cERR_AUDIO_MGR_NO_ERROR; + } + } + if (TrackCount < TRACKWRAP) + { + copyTrack(&Tracks[TrackCount], &track); + TrackCount++; + } + else + { + audio_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP); + return cERR_AUDIO_MGR_ERROR; + } + if (TrackCount > 0) + { + context->playback->isAudio = 1; + } + audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + return cERR_AUDIO_MGR_NO_ERROR; +} + +static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused))) +{ + int i = 0; + TrackDescription_t *tracklist = NULL; + audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks != NULL) + { + tracklist = malloc(sizeof(TrackDescription_t) * ((TrackCount) + 1)); + if (tracklist == NULL) + { + audio_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return NULL; + } + int j = 0; + for (i = 0; i < TrackCount; ++i) + { + if (Tracks[i].pending || Tracks[i].Id < 0) + { + continue; + } + tracklist[j].Id = Tracks[i].Id; + tracklist[j].Name = strdup(Tracks[i].Name); + tracklist[j].Encoding = strdup(Tracks[i].Encoding); + ++j; + } + tracklist[j].Id = -1; + } + //audio_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount); + return tracklist; +} + +static int ManagerDel(Context_t *context) +{ + int i = 0; + audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks != NULL) + { + for (i = 0; i < TrackCount; i++) + { + freeTrack(&Tracks[i]); + } + free(Tracks); + Tracks = NULL; + } + else + { + audio_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__); + return cERR_AUDIO_MGR_ERROR; + } + TrackCount = 0; + CurrentTrack = 0; + context->playback->isAudio = 0; + audio_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); + return cERR_AUDIO_MGR_NO_ERROR; +} + + +static int Command(void *_context, ManagerCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_AUDIO_MGR_NO_ERROR; + audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + switch (command) + { + case MANAGER_ADD: + { + Track_t *track = argument; + ret = ManagerAdd(context, *track); + break; + } + case MANAGER_LIST: + { + container_ffmpeg_update_tracks(context, context->playback->uri, 0); + *((TrackDescription_t **)argument) = ManagerList(context); + break; + } + case MANAGER_GET: + { + audio_mgr_printf(20, "%s::%s MANAGER_GET\n", FILENAME, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((int *)argument) = (int)Tracks[CurrentTrack].Id; + } + else + { + *((int *)argument) = (int) - 1; + } + break; + } + case MANAGER_GET_TRACK_DESC: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + TrackDescription_t *track = malloc(sizeof(TrackDescription_t)); + *((TrackDescription_t **)argument) = track; + if (track) + { + memset(track, 0, sizeof(TrackDescription_t)); + track->Id = Tracks[CurrentTrack].Id; + track->Name = strdup(Tracks[CurrentTrack].Name); + track->Encoding = strdup(Tracks[CurrentTrack].Encoding); + } + } + else + { + *((TrackDescription_t **)argument) = NULL; + } + break; + } + case MANAGER_GET_TRACK: + { + audio_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; + } + else + { + *((Track_t **)argument) = NULL; + } + break; + } + case MANAGER_GETENCODING: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_GETNAME: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Name); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_SET: + { + int i; + audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int *)argument)); + for (i = 0; i < TrackCount; i++) + { + if (Tracks[i].Id == *((int *)argument)) + { + CurrentTrack = i; + break; + } + } + if (i == TrackCount) + { + audio_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int *)argument)); + ret = cERR_AUDIO_MGR_ERROR; + } + break; + } + case MANAGER_DEL: + { + ret = ManagerDel(context); + break; + } + case MANAGER_INIT_UPDATE: + { + int i; + for (i = 0; i < TrackCount; i++) + { + Tracks[i].pending = 1; + } + break; + } + default: + audio_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command); + ret = cERR_AUDIO_MGR_ERROR; + break; + } + audio_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__, ret); + return ret; +} + + +struct Manager_s AudioManager = +{ + "Audio", + &Command, + NULL +}; diff --git a/libeplayer3-arm/manager/manager.c b/libeplayer3-arm/manager/manager.c new file mode 100644 index 0000000..00981e9 --- /dev/null +++ b/libeplayer3-arm/manager/manager.c @@ -0,0 +1,116 @@ +/* + * manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include "manager.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +extern Manager_t AudioManager; +extern Manager_t VideoManager; +extern Manager_t SubtitleManager; + +ManagerHandler_t ManagerHandler = +{ + "ManagerHandler", + &AudioManager, + &VideoManager, + &SubtitleManager +}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ +void copyTrack(Track_t *to, Track_t *from) +{ + if (NULL != to && NULL != from) + { + *to = *from; + if (from->Name != NULL) + { + to->Name = strdup(from->Name); + } + else + { + to->Name = strdup("Unknown"); + } + if (from->Encoding != NULL) + { + to->Encoding = strdup(from->Encoding); + } + else + { + to->Encoding = strdup("Unknown"); + } + if (from->language != NULL) + { + to->language = strdup(from->language); + } + else + { + to->language = strdup("Unknown"); + } + } +} + +void freeTrack(Track_t *track) +{ + if (NULL != track) + { + if (track->Name != NULL) + { + free(track->Name); + track->Name = NULL; + } + if (track->Encoding != NULL) + { + free(track->Encoding); + track->Encoding = NULL; + } + if (track->language != NULL) + { + free(track->language); + track->language = NULL; + } + if (track->aacbuf != NULL) + { + free(track->aacbuf); + track->aacbuf = NULL; + } + } +} diff --git a/libeplayer3-arm/manager/subtitle.c b/libeplayer3-arm/manager/subtitle.c new file mode 100644 index 0000000..f7f9a89 --- /dev/null +++ b/libeplayer3-arm/manager/subtitle.c @@ -0,0 +1,335 @@ +/* + * subtitle manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include "manager.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define TRACKWRAP 20 + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define SUBTITLE_MGR_DEBUG +#else +#define SUBTITLE_MGR_SILENT +#endif + + +#ifdef SUBTITLE_MGR_DEBUG + +static short debug_level = 10; + +#define subtitle_mgr_printf(level, x...) do { \ + if (debug_level >= level) printf(x); } while (0) +#else +#define subtitle_mgr_printf(level, x...) +#endif + +#ifndef SUBTITLE_MGR_SILENT +#define subtitle_mgr_err(x...) do { printf(x); } while (0) +#else +#define subtitle_mgr_err(x...) +#endif + +/* Error Constants */ +#define cERR_SUBTITLE_MGR_NO_ERROR 0 +#define cERR_SUBTITLE_MGR_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Track_t *Tracks = NULL; +static int TrackCount = 0; +static int CurrentTrack = -1; //no as default. + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int ManagerAdd(Context_t *context, Track_t track) +{ + uint32_t i = 0; + subtitle_mgr_printf(10, "%s::%s %s %s %d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id); + if (Tracks == NULL) + { + Tracks = malloc(sizeof(Track_t) * TRACKWRAP); + for (i = 0; i < TRACKWRAP; ++i) + { + Tracks[i].Id = -1; + } + } + if (Tracks == NULL) + { + subtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return cERR_SUBTITLE_MGR_ERROR; + } + for (i = 0; i < TRACKWRAP; ++i) + { + if (Tracks[i].Id == track.Id) + { + Tracks[i].pending = 0; + return cERR_SUBTITLE_MGR_NO_ERROR; + } + } + if (TrackCount < TRACKWRAP) + { + copyTrack(&Tracks[TrackCount], &track); + TrackCount++; + } + else + { + subtitle_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP); + return cERR_SUBTITLE_MGR_ERROR; + } + if (TrackCount > 0) + { + context->playback->isSubtitle = 1; + } + subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + return cERR_SUBTITLE_MGR_NO_ERROR; +} + +static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused))) +{ + int i = 0; + TrackDescription_t *tracklist = NULL; + subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks != NULL) + { + tracklist = malloc(sizeof(TrackDescription_t) * ((TrackCount) + 1)); + if (tracklist == NULL) + { + subtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return NULL; + } + int j = 0; + for (i = 0; i < TrackCount; ++i) + { + if (Tracks[i].pending || Tracks[i].Id < 0) + { + continue; + } + tracklist[j].Id = Tracks[i].Id; + tracklist[j].Name = strdup(Tracks[i].Name); + tracklist[j].Encoding = strdup(Tracks[i].Encoding); + ++j; + } + tracklist[j].Id = -1; + } + return tracklist; +} + +static int32_t ManagerDel(Context_t *context, int32_t onlycurrent) +{ + uint32_t i = 0; + subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (onlycurrent == 0) + { + if (Tracks != NULL) + { + for (i = 0; i < TrackCount; i++) + { + freeTrack(&Tracks[i]); + } + free(Tracks); + Tracks = NULL; + } + else + { + subtitle_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__); + return cERR_SUBTITLE_MGR_ERROR; + } + TrackCount = 0; + context->playback->isSubtitle = 0; + } + CurrentTrack = -1; + subtitle_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); + return cERR_SUBTITLE_MGR_NO_ERROR; +} + +static int32_t Command(void *_context, ManagerCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int32_t ret = cERR_SUBTITLE_MGR_NO_ERROR; + subtitle_mgr_printf(50, "%s::%s %d\n", FILENAME, __FUNCTION__, command); + switch (command) + { + case MANAGER_ADD: + { + Track_t *track = argument; + ret = ManagerAdd(context, *track); + break; + } + case MANAGER_LIST: + { + container_ffmpeg_update_tracks(context, context->playback->uri, 0); + *((char ** *)argument) = (char **)ManagerList(context); + break; + } + case MANAGER_GET: + { + if (TrackCount > 0 && CurrentTrack >= 0) + { + *((int *)argument) = (int)Tracks[CurrentTrack].Id; + } + else + { + *((int *)argument) = (int) - 1; + } + break; + } + case MANAGER_GET_TRACK_DESC: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + TrackDescription_t *track = malloc(sizeof(TrackDescription_t)); + *((TrackDescription_t **)argument) = track; + if (track) + { + memset(track, 0, sizeof(TrackDescription_t)); + track->Id = Tracks[CurrentTrack].Id; + track->Name = strdup(Tracks[CurrentTrack].Name); + track->Encoding = strdup(Tracks[CurrentTrack].Encoding); + } + } + else + { + *((TrackDescription_t **)argument) = NULL; + } + break; + } + case MANAGER_GET_TRACK: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; + } + else + { + *((Track_t **)argument) = NULL; + } + break; + } + case MANAGER_GETENCODING: + { + if (TrackCount > 0 && CurrentTrack >= 0) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_GETNAME: + { + if (TrackCount > 0 && CurrentTrack >= 0) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Name); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_SET: + { + uint32_t i = 0; + int32_t requestedTrackId = *((int *)argument); + subtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int *)argument)); + if (requestedTrackId == -1) + { + // track id -1 mean disable subtitle + CurrentTrack = -1; + break; + } + for (i = 0; i < TrackCount; ++i) + { + if (Tracks[i].Id == requestedTrackId) + { + CurrentTrack = i; + break; + } + } + if (i == TrackCount) + { + subtitle_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int *)argument)); + ret = cERR_SUBTITLE_MGR_ERROR; + } + break; + } + case MANAGER_DEL: + { + if (argument == NULL) + { + ret = ManagerDel(context, 0); + } + else + { + ret = ManagerDel(context, *((int *)argument)); + } + break; + } + case MANAGER_INIT_UPDATE: + { + uint32_t i; + for (i = 0; i < TrackCount; i++) + { + Tracks[i].pending = 1; + } + break; + } + default: + subtitle_mgr_err("%s:%s: ConatinerCmd not supported!", FILENAME, __FUNCTION__); + ret = cERR_SUBTITLE_MGR_ERROR; + break; + } + subtitle_mgr_printf(50, "%s:%s: returning %d\n", FILENAME, __FUNCTION__, ret); + return ret; +} + + +Manager_t SubtitleManager = +{ + "Subtitle", + &Command, + NULL +}; diff --git a/libeplayer3-arm/manager/video.c b/libeplayer3-arm/manager/video.c new file mode 100644 index 0000000..32af5b5 --- /dev/null +++ b/libeplayer3-arm/manager/video.c @@ -0,0 +1,336 @@ +/* + * video manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include "manager.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define TRACKWRAP 4 + +#ifdef SAM_WITH_DEBUG +#define VIDEO_MGR_DEBUG +#else +#define VIDEO_MGR_SILENT +#endif + +#ifdef VIDEO_MGR_DEBUG + +static short debug_level = 0; + +#define video_mgr_printf(level, x...) do { \ + if (debug_level >= level) printf(x); } while (0) +#else +#define video_mgr_printf(level, x...) +#endif + +#ifndef VIDEO_MGR_SILENT +#define video_mgr_err(x...) do { printf(x); } while (0) +#else +#define video_mgr_err(x...) +#endif + +/* Error Constants */ +#define cERR_VIDEO_MGR_NO_ERROR 0 +#define cERR_VIDEO_MGR_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Track_t *Tracks = NULL; +static int TrackCount = 0; +static int CurrentTrack = 0; //TRACK[0] as default. + +static void (* updatedTrackInfoFnc)(void) = NULL; +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int ManagerAdd(Context_t *context, Track_t track) +{ + video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks == NULL) + { + Tracks = malloc(sizeof(Track_t) * TRACKWRAP); + int i; + for (i = 0; i < TRACKWRAP; i++) + { + Tracks[i].Id = -1; + } + } + if (Tracks == NULL) + { + video_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return cERR_VIDEO_MGR_ERROR; + } + int i; + for (i = 0; i < TRACKWRAP; i++) + { + if (Tracks[i].Id == track.Id) + { + Tracks[i].pending = 0; + return cERR_VIDEO_MGR_NO_ERROR; + } + } + if (TrackCount < TRACKWRAP) + { + copyTrack(&Tracks[TrackCount], &track); + TrackCount++; + } + else + { + video_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP); + return cERR_VIDEO_MGR_ERROR; + } + if (TrackCount > 0) + { + context->playback->isVideo = 1; + } + video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + return cERR_VIDEO_MGR_NO_ERROR; +} + +static char **ManagerList(Context_t *context __attribute__((unused))) +{ + int i = 0, j = 0; + char **tracklist = NULL; + video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks != NULL) + { + tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1)); + if (tracklist == NULL) + { + video_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return NULL; + } + for (i = 0, j = 0; i < TrackCount; i++, j += 2) + { + if (Tracks[i].pending) + { + continue; + } + size_t len = strlen(Tracks[i].Name) + 20; + char tmp[len]; + snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name); + tracklist[j] = strdup(tmp); + tracklist[j + 1] = strdup(Tracks[i].Encoding); + } + tracklist[j] = NULL; + } + video_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount); + return tracklist; +} + +static int ManagerDel(Context_t *context) +{ + int i = 0; + video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (Tracks != NULL) + { + for (i = 0; i < TrackCount; i++) + { + freeTrack(&Tracks[i]); + } + free(Tracks); + Tracks = NULL; + } + else + { + video_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__); + return cERR_VIDEO_MGR_ERROR; + } + TrackCount = 0; + CurrentTrack = 0; + context->playback->isVideo = 0; + video_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); + return cERR_VIDEO_MGR_NO_ERROR; +} + +static int Command(void *_context, ManagerCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_VIDEO_MGR_NO_ERROR; + video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + switch (command) + { + case MANAGER_ADD: + { + Track_t *track = argument; + ret = ManagerAdd(context, *track); + break; + } + case MANAGER_LIST: + { + container_ffmpeg_update_tracks(context, context->playback->uri, 0); + *((char ** *)argument) = (char **)ManagerList(context); + break; + } + case MANAGER_GET: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((int *)argument) = (int)Tracks[CurrentTrack].Id; + } + else + { + *((int *)argument) = (int) - 1; + } + break; + } + case MANAGER_GET_TRACK_DESC: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + TrackDescription_t *track = malloc(sizeof(TrackDescription_t)); + *((TrackDescription_t **)argument) = track; + if (track) + { + memset(track, 0, sizeof(TrackDescription_t)); + track->Id = Tracks[CurrentTrack].Id; + track->Name = strdup(Tracks[CurrentTrack].Name); + track->Encoding = strdup(Tracks[CurrentTrack].Encoding); + track->frame_rate = Tracks[CurrentTrack].frame_rate; + track->width = Tracks[CurrentTrack].width; + track->height = Tracks[CurrentTrack].height; + track->aspect_ratio_num = Tracks[CurrentTrack].aspect_ratio_num; + track->aspect_ratio_den = Tracks[CurrentTrack].aspect_ratio_den; + context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, &(track->progressive)); + } + } + else + { + *((TrackDescription_t **)argument) = NULL; + } + break; + } + case MANAGER_GET_TRACK: + { + video_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; + } + else + { + *((Track_t **)argument) = NULL; + } + break; + } + case MANAGER_GETENCODING: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_GETNAME: + { + if ((TrackCount > 0) && (CurrentTrack >= 0)) + { + *((char **)argument) = (char *)strdup(Tracks[CurrentTrack].Name); + } + else + { + *((char **)argument) = (char *)strdup(""); + } + break; + } + case MANAGER_SET: + { + int i; + for (i = 0; i < TrackCount; i++) + { + if (Tracks[i].Id == *((int *)argument)) + { + CurrentTrack = i; + break; + } + } + if (i == TrackCount) + { + video_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int *)argument)); + ret = cERR_VIDEO_MGR_ERROR; + } + break; + } + case MANAGER_DEL: + { + ret = ManagerDel(context); + break; + } + case MANAGER_INIT_UPDATE: + { + int i; + for (i = 0; i < TrackCount; i++) + { + Tracks[i].pending = 1; + } + break; + } + case MANAGER_UPDATED_TRACK_INFO: + { + if (updatedTrackInfoFnc != NULL) + updatedTrackInfoFnc(); + break; + } + case MANAGER_REGISTER_UPDATED_TRACK_INFO: + { + updatedTrackInfoFnc = (void (*)(void))argument; + break; + } + default: + video_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command); + ret = cERR_VIDEO_MGR_ERROR; + break; + } + video_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__, ret); + return ret; +} + + +struct Manager_s VideoManager = +{ + "Video", + &Command, + NULL +}; diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c new file mode 100644 index 0000000..224ca53 --- /dev/null +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -0,0 +1,1118 @@ +/* + * LinuxDVB Output handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "writer.h" +#include "misc.h" +#include "pes.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +// SULGE DEBUG +//#define SAM_WITH_DEBUG + +#ifdef SAM_WITH_DEBUG +#define LINUXDVB_DEBUG +#else +#define LINUXDVB_SILENT +#endif + +static short debug_level = 20; + +static const char FILENAME[] = __FILE__; + +#ifdef LINUXDVB_DEBUG +#define linuxdvb_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x ); } while (0) +#else +#define linuxdvb_printf(level, fmt, x...) +#endif + +#ifndef LINUXDVB_SILENT +#define linuxdvb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define linuxdvb_err(fmt, x...) +#endif + +#define cERR_LINUXDVB_NO_ERROR 0 +#define cERR_LINUXDVB_ERROR -1 + +static const char VIDEODEV[] = "/dev/dvb/adapter0/video0"; +static const char AUDIODEV[] = "/dev/dvb/adapter0/audio0"; + +static int videofd = -1; +static int audiofd = -1; + +struct DVBApiVideoInfo_s +{ + int aspect_ratio; + int progressive; + int frame_rate; + int width, height; +}; +static struct DVBApiVideoInfo_s videoInfo = {-1, -1, -1, -1, -1}; + +unsigned long long int sCURRENT_PTS = 0; + +pthread_mutex_t LinuxDVBmutex; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ +int LinuxDvbStop(Context_t *context, char *type); + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +void getLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) +{ + linuxdvb_printf(250, "requesting mutex\n"); + pthread_mutex_lock(&LinuxDVBmutex); + linuxdvb_printf(250, "received mutex\n"); +} + +void releaseLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) +{ + pthread_mutex_unlock(&LinuxDVBmutex); + linuxdvb_printf(250, "released mutex\n"); +} + +static int LinuxDvbMapBypassMode(int bypass) +{ + if (0x30 == bypass && IsDreambox()) + { + return 0x0f; + } + return bypass; +} + +int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) +{ + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd < 0) + { + videofd = open(VIDEODEV, O_RDWR | O_CLOEXEC); + if (videofd < 0) + { + linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno); + linuxdvb_err("%s\n", strerror(errno)); + return cERR_LINUXDVB_ERROR; + } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_SELECT_SOURCE, (void *)VIDEO_SOURCE_MEMORY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_FREEZE) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); + } + } + if (audio && audiofd < 0) + { + audiofd = open(AUDIODEV, O_RDWR | O_CLOEXEC); + if (audiofd < 0) + { + linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); + linuxdvb_err("%s\n", strerror(errno)); + return cERR_LINUXDVB_ERROR; + } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_PAUSE) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); + } + } + return cERR_LINUXDVB_NO_ERROR; +} + +int LinuxDvbClose(Context_t *context, char *type) +{ + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + /* closing stand alone is not allowed, so prevent + * user from closing and don't call stop. stop will + * set default values for us (speed and so on). + */ + LinuxDvbStop(context, type); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + close(videofd); + videofd = -1; + } + if (audio && audiofd != -1) + { + close(audiofd); + audiofd = -1; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return cERR_LINUXDVB_NO_ERROR; +} + +int LinuxDvbPlay(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + Writer_t *writer; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + // SULGE VU 4K dont like this + /* + if (0 != ioctl(videofd, VIDEO_STOP)) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + */ + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) writer->caps->dvbStreamType) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + free(Encoding); + if (0 != ioctl(videofd, VIDEO_PLAY)) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + if (ioctl(videofd, VIDEO_CONTINUE) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + } + if (audio && audiofd != -1) + { + char *Encoding = NULL; + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "0 A %s\n", Encoding); + writer = getWriter(Encoding); + // SULGE VU 4K dont like this + /* + if (0 != ioctl(audiofd, AUDIO_STOP)) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + */ + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(audiofd, AUDIO_SET_BYPASS_MODE, (void *) LinuxDvbMapBypassMode(writer->caps->dvbStreamType)) < 0) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (ioctl(audiofd, AUDIO_PLAY) < 0) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + if (ioctl(audiofd, AUDIO_CONTINUE) < 0) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + free(Encoding); + } + //return ret; + return 0; +} + +int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_STOP) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + ioctl(videofd, VIDEO_SLOWMOTION, 0); + ioctl(videofd, VIDEO_FAST_FORWARD, 0); + ioctl(videofd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + /* set back to normal speed (end trickmodes) */ + // if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); + // } + if (ioctl(audiofd, AUDIO_STOP) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX); + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; +} + +int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; +} + +int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + +int LinuxDvbReverseDiscontinuity(Context_t *context __attribute__((unused)), int *surplus) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + // int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus; + // linuxdvb_printf(50, "\n"); + // if (ioctl( videofd, VIDEO_DISCONTINUITY, (void*) dis_type) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno)); + // } + // linuxdvb_printf(50, "exiting\n"); + return ret; +} + +int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(10, "\n"); + if (audiofd != -1) + { + if (*flag == '1') + { + //AUDIO_SET_MUTE has no effect with new player + //if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1) + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else + { + //AUDIO_SET_MUTE has no effect with new player + //if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1) + if (ioctl(audiofd, AUDIO_PLAY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + + +int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) +{ + // unsigned char video = !strcmp("video", type); + // unsigned char audio = !strcmp("audio", type); + // linuxdvb_printf(10, "v%d a%d\n", video, audio); + // if ( (video && videofd != -1) || (audio && audiofd != -1) ) { + // getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + // if (video && videofd != -1) { + // if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno)); + // } + // } + // if (audio && audiofd != -1) { + // if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno)); + // } + // } + // releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + // } + // linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; +} + +#ifndef use_set_speed_instead_ff +int LinuxDvbFastForward(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); + if (video && videofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + /* konfetti comment: speed is a value given in skipped frames */ + if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} +#else + +static unsigned int SpeedList[] = +{ + 1000, 1100, 1200, 1300, 1500, + 2000, 3000, 4000, 5000, 8000, + 12000, 16000, + 125, 250, 500, 700, 800, 900 +}; + +int LinuxDvbFastForward(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + int speedIndex; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + // if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); + // ret = cERR_LINUXDVB_ERROR; + // } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + if (audio && audiofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + // if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); + // ret = cERR_LINUXDVB_ERROR; + // } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} +#endif + + +int LinuxDvbReverse(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + return ret; +} + +int LinuxDvbSlowMotion(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} + +int LinuxDvbAVSync(Context_t *context, char *type __attribute__((unused))) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + /* konfetti: this one is dedicated to audiofd so we + * are ignoring what is given by type! I think we should + * remove this param. Therefor we should add a variable + * setOn or something like that instead, this would remove + * using a variable inside the structure. + */ + if (audiofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (ioctl(audiofd, AUDIO_SET_AV_SYNC, 0) == -1) //context->playback->AVSync) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + return ret; +} + +int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) +{ + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, ">>>>>>>>>>LinuxDvbClear v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + +int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts) +{ + int ret = cERR_LINUXDVB_ERROR; + linuxdvb_printf(50, "\n"); + // pts is a non writting requests and can be done in parallel to other requests + //getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *)&sCURRENT_PTS)) + { + ret = cERR_LINUXDVB_NO_ERROR; + } + else + { + linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + } + if (ret != cERR_LINUXDVB_NO_ERROR) + { + if (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *)&sCURRENT_PTS)) + { + ret = cERR_LINUXDVB_NO_ERROR; + } + else + { + linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + } + } + if (ret != cERR_LINUXDVB_NO_ERROR) + { + sCURRENT_PTS = 0; + } + *((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS; + //releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + return ret; +} + +int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned long long int *frameCount) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + return ret; +} + +int LinuxDvbSwitch(Context_t *context, char *type) +{ + unsigned char audio = !strcmp("audio", type); + unsigned char video = !strcmp("video", type); + Writer_t *writer; + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (audio && audiofd != -1) + { + char *Encoding = NULL; + if (context && context->manager && context->manager->audio) + { + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "A %s\n", Encoding); + writer = getWriter(Encoding); + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + // if (ioctl( audiofd, AUDIO_SET_BYPASS_MODE, (void*) AUDIO_ENCODING_MP3) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); + // } + } + else + { + linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(audiofd, AUDIO_SET_BYPASS_MODE, (void *) LinuxDvbMapBypassMode(writer->caps->dvbStreamType)) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); + } + } + if (ioctl(audiofd, AUDIO_PLAY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + } + free(Encoding); + } + else + linuxdvb_printf(20, "no context for Audio\n"); + } + if (video && videofd != -1) + { + char *Encoding = NULL; + if (context && context->manager && context->manager->video) + { + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + if (ioctl(videofd, VIDEO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + // if (ioctl( videofd, VIDEO_SET_STREAMTYPE, (void*) VIDEO_ENCODING_AUTO) == -1) + // { + // linuxdvb_err("ioctl failed with errno %d\n", errno); + // linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + // } + } + else + { + linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) writer->caps->dvbStreamType) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + } + } + if (ioctl(videofd, VIDEO_PLAY) == -1) + { + /* konfetti: fixme: think on this, I think we should + * return an error here and stop the playback mode + */ + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + } + free(Encoding); + } + else + linuxdvb_printf(20, "no context for Video\n"); + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; +} + +static int Write(void *_context, void *_out) +{ + Context_t *context = (Context_t *) _context; + AudioVideoOut_t *out = (AudioVideoOut_t *) _out; + int ret = cERR_LINUXDVB_NO_ERROR; + int res = 0; + unsigned char video = 0; + unsigned char audio = 0; + Writer_t *writer; + WriterAVCallData_t call; + if (out == NULL) + { + linuxdvb_err("null pointer passed\n"); + return cERR_LINUXDVB_ERROR; + } + video = !strcmp("video", out->type); + audio = !strcmp("audio", out->type); + linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n", + out->len, out->extralen, out->pts, out->frameRate); + linuxdvb_printf(20, "v%d a%d\n", video, audio); + if (video) + { + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "Encoding = %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); + writer = getDefaultVideoWriter(); + } + if (writer == NULL) + { + linuxdvb_err("unknown video codec and no default writer %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + struct pollfd pfd[1]; + pfd[0].fd = videofd; + pfd[0].events = POLLPRI; + int pollret = poll(pfd, 1, 0); + if (pollret > 0 && pfd[0].revents & POLLPRI) + { + struct video_event evt; + if (ioctl(videofd, VIDEO_GET_EVENT, &evt) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_GET_EVENT: %s\n", strerror(errno)); + } + else + { + if (evt.type == VIDEO_EVENT_SIZE_CHANGED) + { + linuxdvb_printf(10, "VIDEO_EVENT_SIZE_CHANGED\n", evt.type); + linuxdvb_printf(10, "width : %d\n", evt.u.size.w); + linuxdvb_printf(10, "height : %d\n", evt.u.size.h); + linuxdvb_printf(10, "aspect : %d\n", evt.u.size.aspect_ratio); + videoInfo.width = evt.u.size.w; + videoInfo.height = evt.u.size.h; + videoInfo.aspect_ratio = evt.u.size.aspect_ratio; + } + else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED) + { + linuxdvb_printf(10, "VIDEO_EVENT_FRAME_RATE_CHANGED\n", evt.type); + linuxdvb_printf(10, "framerate : %d\n", evt.u.frame_rate); + videoInfo.frame_rate = evt.u.frame_rate; + } + else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/) + { + linuxdvb_printf(10, "VIDEO_EVENT_PROGRESSIVE_CHANGED\n", evt.type); + linuxdvb_printf(10, "progressive : %d\n", evt.u.frame_rate); + videoInfo.progressive = evt.u.frame_rate; + context->manager->video->Command(context, MANAGER_UPDATED_TRACK_INFO, NULL); + } + else + { + linuxdvb_err("unhandled DVBAPI Video Event %d\n", evt.type); + } + } + } + call.fd = videofd; + call.data = out->data; + call.len = out->len; + call.Pts = out->pts; + call.Dts = out->dts; + call.private_data = out->extradata; + call.private_size = out->extralen; + call.FrameRate = out->frameRate; + call.FrameScale = out->timeScale; + call.Width = out->width; + call.Height = out->height; + call.InfoFlags = out->infoFlags; + call.Version = 0; // is unsingned char + if (writer->writeData) + { + res = writer->writeData(&call); + } + if (res < 0) + { + linuxdvb_err("failed to write data %d - %d\n", res, errno); + linuxdvb_err("%s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + free(Encoding); + } + else if (audio) + { + char *Encoding = NULL; + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); + writer = getDefaultAudioWriter(); + } + if (writer == NULL) + { + linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + call.fd = audiofd; + call.data = out->data; + call.len = out->len; + call.Pts = out->pts; + call.Dts = out->dts; + call.private_data = out->extradata; + call.private_size = out->extralen; + call.FrameRate = out->frameRate; + call.FrameScale = out->timeScale; + call.InfoFlags = out->infoFlags; + call.Version = 0; /* -1; unsigned char cannot be negative */ + if (writer->writeData) + { + res = writer->writeData(&call); + } + if (res < 0) + { + linuxdvb_err("failed to write data %d - %d\n", res, errno); + linuxdvb_err("%s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + free(Encoding); + } + return ret; +} + +static int reset(Context_t *context) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + Writer_t *writer; + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("unknown video codec %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + writer->reset(); + } + free(Encoding); + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("unknown video codec %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + writer->reset(); + } + free(Encoding); + return ret; +} + +static int Command(void *_context, OutputCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(50, "Command %d\n", command); + switch (command) + { + case OUTPUT_OPEN: + { + ret = LinuxDvbOpen(context, (char *)argument); + break; + } + case OUTPUT_CLOSE: + { + ret = LinuxDvbClose(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PLAY: // 4 + { + sCURRENT_PTS = 0; + ret = LinuxDvbPlay(context, (char *)argument); + break; + } + case OUTPUT_STOP: + { + reset(context); + ret = LinuxDvbStop(context, (char *)argument); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_FLUSH: + { + ret = LinuxDvbFlush(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PAUSE: + { + ret = LinuxDvbPause(context, (char *)argument); + break; + } + case OUTPUT_CONTINUE: + { + ret = LinuxDvbContinue(context, (char *)argument); + break; + } + case OUTPUT_FASTFORWARD: + { + return LinuxDvbFastForward(context, (char *)argument); + break; + } + case OUTPUT_REVERSE: + { + return LinuxDvbReverse(context, (char *)argument); + break; + } + case OUTPUT_AVSYNC: + { + ret = LinuxDvbAVSync(context, (char *)argument); + break; + } + case OUTPUT_CLEAR: + { + ret = LinuxDvbClear(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PTS: + { + unsigned long long int pts = 0; + ret = LinuxDvbPts(context, &pts); + *((unsigned long long int *)argument) = (unsigned long long int)pts; + break; + } + case OUTPUT_SWITCH: + { + ret = LinuxDvbSwitch(context, (char *)argument); + break; + } + case OUTPUT_SLOWMOTION: + { + return LinuxDvbSlowMotion(context, (char *)argument); + break; + } + case OUTPUT_AUDIOMUTE: + { + return LinuxDvbAudioMute(context, (char *)argument); + break; + } + case OUTPUT_DISCONTINUITY_REVERSE: + { + return LinuxDvbReverseDiscontinuity(context, (int *)argument); + break; + } + case OUTPUT_GET_FRAME_COUNT: + { + unsigned long long int frameCount = 0; + ret = LinuxDvbGetFrameCount(context, &frameCount); + *((unsigned long long int *)argument) = (unsigned long long int)frameCount; + break; + } + case OUTPUT_GET_PROGRESSIVE: + { + ret = cERR_LINUXDVB_NO_ERROR; + *((int *)argument) = videoInfo.progressive; + break; + } + default: + linuxdvb_err("ContainerCmd %d not supported!\n", command); + ret = cERR_LINUXDVB_ERROR; + break; + } + linuxdvb_printf(50, "exiting with value %d\n", ret); + return ret; +} + +static char *LinuxDvbCapabilities[] = { "audio", "video", NULL }; + +struct Output_s LinuxDvbOutput = +{ + "LinuxDvb", + &Command, + &Write, + LinuxDvbCapabilities +}; diff --git a/libeplayer3-arm/output/linuxdvb_sh4.c b/libeplayer3-arm/output/linuxdvb_sh4.c new file mode 100644 index 0000000..1ffb854 --- /dev/null +++ b/libeplayer3-arm/output/linuxdvb_sh4.c @@ -0,0 +1,1122 @@ +/* + * LinuxDVB Output handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "writer.h" +#include "misc.h" +#include "pes.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +//#define LINUXDVB_DEBUG +#define LINUXDVB_SILENT + +static unsigned short debug_level = 0; + +static const char FILENAME[] = __FILE__; + +#ifdef LINUXDVB_DEBUG +#define linuxdvb_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x ); } while (0) +#else +#define linuxdvb_printf(x...) +#endif + +#ifndef LINUXDVB_SILENT +#define linuxdvb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define linuxdvb_err(x...) +#endif + +#define cERR_LINUXDVB_NO_ERROR 0 +#define cERR_LINUXDVB_ERROR -1 + +static const char VIDEODEV[] = "/dev/dvb/adapter0/video0"; +static const char AUDIODEV[] = "/dev/dvb/adapter0/audio0"; + +static int videofd = -1; +static int audiofd = -1; + +struct DVBApiVideoInfo_s +{ + int aspect_ratio; + int progressive; + int frame_rate; + int width, height; +}; +static struct DVBApiVideoInfo_s videoInfo = {-1, -1, -1, -1, -1}; + +unsigned long long int sCURRENT_PTS = 0; + +pthread_mutex_t LinuxDVBmutex; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ +int LinuxDvbStop(Context_t *context, char *type); + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +void getLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) +{ + linuxdvb_printf(250, "requesting mutex\n"); + pthread_mutex_lock(&LinuxDVBmutex); + linuxdvb_printf(250, "received mutex\n"); +} + +void releaseLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) +{ + pthread_mutex_unlock(&LinuxDVBmutex); + linuxdvb_printf(250, "released mutex\n"); +} + +int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) +{ + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd < 0) + { + videofd = open(VIDEODEV, O_RDWR); + if (videofd < 0) + { + linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno); + linuxdvb_err("%s\n", strerror(errno)); + return cERR_LINUXDVB_ERROR; + } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_SELECT_SOURCE, (void *)VIDEO_SOURCE_MEMORY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *)STREAM_TYPE_PROGRAM) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); + } + } + if (audio && audiofd < 0) + { + audiofd = open(AUDIODEV, O_RDWR); + if (audiofd < 0) + { + linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); + linuxdvb_err("%s\n", strerror(errno)); + if (videofd < 0) + close(videofd); + return cERR_LINUXDVB_ERROR; + } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_SELECT_SOURCE, (void *)AUDIO_SOURCE_MEMORY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_SET_STREAMTYPE, (void *)STREAM_TYPE_PROGRAM) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno)); + } + } + return cERR_LINUXDVB_NO_ERROR; +} + +int LinuxDvbClose(Context_t *context, char *type) +{ + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + /* closing stand alone is not allowed, so prevent + * user from closing and dont call stop. stop will + * set default values for us (speed and so on). + */ + LinuxDvbStop(context, type); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + close(videofd); + videofd = -1; + } + if (audio && audiofd != -1) + { + close(audiofd); + audiofd = -1; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return cERR_LINUXDVB_NO_ERROR; +} + +int LinuxDvbPlay(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + Writer_t *writer; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + if (ioctl(videofd, VIDEO_SET_ENCODING, (void *) VIDEO_ENCODING_AUTO) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else + { + linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(videofd, VIDEO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + free(Encoding); + } + if (audio && audiofd != -1) + { + char *Encoding = NULL; + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "0 A %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + if (ioctl(audiofd, AUDIO_SET_ENCODING, (void *)AUDIO_ENCODING_MP3) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else + { + linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(audiofd, AUDIO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); + ret = -1; + } + } + if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + free(Encoding); + } + return ret; +} + +int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + /* set back to normal speed (end trickmodes) */ + if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + /* set back to normal speed (end trickmodes) */ + if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; +} + +int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; +} + +int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + +int LinuxDvbReverseDiscontinuity(Context_t *context __attribute__((unused)), int *surplus) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus; + linuxdvb_printf(50, "\n"); + if (ioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno)); + } + linuxdvb_printf(50, "exiting\n"); + return ret; +} + +int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(10, "\n"); + if (audiofd != -1) + { + if (*flag == '1') + { + //AUDIO_SET_MUTE has no effect with new player + //if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1) + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else + { + //AUDIO_SET_MUTE has no effect with new player + //if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1) + if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + + +int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) +{ + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno)); + } + } + if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno)); + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; +} + +#ifndef use_set_speed_instead_ff +int LinuxDvbFastForward(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); + if (video && videofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + /* konfetti comment: speed is a value given in skipped frames */ + if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} +#else + +static unsigned int SpeedList[] = +{ + 1000, 1100, 1200, 1300, 1500, + 2000, 3000, 4000, 5000, 8000, + 12000, 16000, + 125, 250, 500, 700, 800, 900 +}; + +int LinuxDvbFastForward(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + int speedIndex; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + if (audio && audiofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} +#endif + + +int LinuxDvbReverse(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + return ret; +} + +int LinuxDvbSlowMotion(Context_t *context, char *type) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); + unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; +} + +int LinuxDvbAVSync(Context_t *context, char *type __attribute__((unused))) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + /* konfetti: this one is dedicated to audiofd so we + * are ignoring what is given by type! I think we should + * remove this param. Therefor we should add a variable + * setOn or something like that instead, this would remove + * using a variable inside the structure. + */ + if (audiofd != -1) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (ioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + return ret; +} + +int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) +{ + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, ">>>>>>>>>>LinuxDvbClear v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) + { + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + else if (audio && audiofd != -1) + { + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return ret; +} + +int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts) +{ + int ret = cERR_LINUXDVB_ERROR; + linuxdvb_printf(50, "\n"); + // pts is a non writting requests and can be done in parallel to other requests + //getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *)&sCURRENT_PTS)) + { + ret = cERR_LINUXDVB_NO_ERROR; + } + else + { + linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + } + if (ret != cERR_LINUXDVB_NO_ERROR) + { + if (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *)&sCURRENT_PTS)) + { + ret = cERR_LINUXDVB_NO_ERROR; + } + else + { + linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + } + } + if (ret != cERR_LINUXDVB_NO_ERROR) + { + sCURRENT_PTS = 0; + } + *((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS; + //releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + return ret; +} + +int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned long long int *frameCount) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + dvb_play_info_t playInfo; + linuxdvb_printf(50, "\n"); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (videofd != -1) + { + if (ioctl(videofd, VIDEO_GET_PLAY_INFO, (void *)&playInfo) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_GET_PLAY_INFO: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + else linuxdvb_err("V: %llu\n", playInfo.frame_count); + } + else if (audiofd != -1) + { + if (ioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *)&playInfo) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_GET_PLAY_INFO: %s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + else linuxdvb_err("A: %llu\n", playInfo.frame_count); + } + else + { + ret = cERR_LINUXDVB_ERROR; + } + if (ret == cERR_LINUXDVB_NO_ERROR) + *((unsigned long long int *)frameCount) = playInfo.frame_count; + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; +} + +int LinuxDvbSwitch(Context_t *context, char *type) +{ + unsigned char audio = !strcmp("audio", type); + unsigned char video = !strcmp("video", type); + Writer_t *writer; + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) + { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (audio && audiofd != -1) + { + char *Encoding = NULL; + if (context && context->manager && context->manager->audio) + { + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "A %s\n", Encoding); + writer = getWriter(Encoding); + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + if (ioctl(audiofd, AUDIO_SET_ENCODING, (void *) AUDIO_ENCODING_MP3) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); + } + } + else + { + linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(audiofd, AUDIO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); + } + } + if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + } + free(Encoding); + } + else + linuxdvb_printf(20, "no context for Audio\n"); + } + if (video && videofd != -1) + { + char *Encoding = NULL; + if (context && context->manager && context->manager->video) + { + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + if (ioctl(videofd, VIDEO_STOP, NULL) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); + } + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); + if (ioctl(videofd, VIDEO_SET_ENCODING, (void *) VIDEO_ENCODING_AUTO) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); + } + } + else + { + linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); + if (ioctl(videofd, VIDEO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); + } + } + if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) + { + /* konfetti: fixme: think on this, I think we should + * return an error here and stop the playback mode + */ + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + } + free(Encoding); + } + else + linuxdvb_printf(20, "no context for Video\n"); + } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; +} + +static int Write(void *_context, void *_out) +{ + Context_t *context = (Context_t *) _context; + AudioVideoOut_t *out = (AudioVideoOut_t *) _out; + int ret = cERR_LINUXDVB_NO_ERROR; + int res = 0; + unsigned char video = 0; + unsigned char audio = 0; + Writer_t *writer; + WriterAVCallData_t call; + if (out == NULL) + { + linuxdvb_err("null pointer passed\n"); + return cERR_LINUXDVB_ERROR; + } + video = !strcmp("video", out->type); + audio = !strcmp("audio", out->type); + linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n", + out->len, out->extralen, out->pts, out->frameRate); + linuxdvb_printf(20, "v%d a%d\n", video, audio); + if (video) + { + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "Encoding = %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); + writer = getDefaultVideoWriter(); + } + if (writer == NULL) + { + linuxdvb_err("unknown video codec and no default writer %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + struct pollfd pfd[1]; + pfd[0].fd = videofd; + pfd[0].events = POLLPRI; + int pollret = poll(pfd, 1, 0); + if (pollret > 0 && pfd[0].revents & POLLPRI) + { + struct video_event evt; + if (ioctl(videofd, VIDEO_GET_EVENT, &evt) == -1) + { + linuxdvb_err("ioctl failed with errno %d\n", errno); + linuxdvb_err("VIDEO_GET_EVENT: %s\n", strerror(errno)); + } + else + { + if (evt.type == VIDEO_EVENT_SIZE_CHANGED) + { + linuxdvb_printf(10, "VIDEO_EVENT_SIZE_CHANGED\n", evt.type); + linuxdvb_printf(10, "width : %d\n", evt.u.size.w); + linuxdvb_printf(10, "height : %d\n", evt.u.size.h); + linuxdvb_printf(10, "aspect : %d\n", evt.u.size.aspect_ratio); + videoInfo.width = evt.u.size.w; + videoInfo.height = evt.u.size.h; + videoInfo.aspect_ratio = evt.u.size.aspect_ratio; + } + else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED) + { + linuxdvb_printf(10, "VIDEO_EVENT_FRAME_RATE_CHANGED\n", evt.type); + linuxdvb_printf(10, "framerate : %d\n", evt.u.frame_rate); + videoInfo.frame_rate = evt.u.frame_rate; + } + else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/) + { + linuxdvb_printf(10, "VIDEO_EVENT_PROGRESSIVE_CHANGED\n", evt.type); + linuxdvb_printf(10, "progressive : %d\n", evt.u.frame_rate); + videoInfo.progressive = evt.u.frame_rate; + context->manager->video->Command(context, MANAGER_UPDATED_TRACK_INFO, NULL); + } + else + { + linuxdvb_err("unhandled DVBAPI Video Event %d\n", evt.type); + } + } + } + call.fd = videofd; + call.data = out->data; + call.len = out->len; + call.Pts = out->pts; + call.Dts = out->dts; + call.private_data = out->extradata; + call.private_size = out->extralen; + call.FrameRate = out->frameRate; + call.FrameScale = out->timeScale; + call.Width = out->width; + call.Height = out->height; + call.InfoFlags = out->infoFlags; + call.Version = 0; // is unsingned char + if (writer->writeData) + { + res = writer->writeData(&call); + } + if (res < 0) + { + linuxdvb_err("failed to write data %d - %d\n", res, errno); + linuxdvb_err("%s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + free(Encoding); + } + else if (audio) + { + char *Encoding = NULL; + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); + writer = getDefaultAudioWriter(); + } + if (writer == NULL) + { + linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + call.fd = audiofd; + call.data = out->data; + call.len = out->len; + call.Pts = out->pts; + call.Dts = out->dts; + call.private_data = out->extradata; + call.private_size = out->extralen; + call.FrameRate = out->frameRate; + call.FrameScale = out->timeScale; + call.InfoFlags = out->infoFlags; + call.Version = 0; /* -1; unsigned char cannot be negative */ + if (writer->writeData) + { + res = writer->writeData(&call); + } + if (res < 0) + { + linuxdvb_err("failed to write data %d - %d\n", res, errno); + linuxdvb_err("%s\n", strerror(errno)); + ret = cERR_LINUXDVB_ERROR; + } + } + free(Encoding); + } + return ret; +} + +static int reset(Context_t *context) +{ + int ret = cERR_LINUXDVB_NO_ERROR; + Writer_t *writer; + char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("unknown video codec %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + writer->reset(); + } + free(Encoding); + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) + { + linuxdvb_err("unknown video codec %s\n", Encoding); + ret = cERR_LINUXDVB_ERROR; + } + else + { + writer->reset(); + } + free(Encoding); + return ret; +} + +static int Command(void *_context, OutputCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(50, "Command %d\n", command); + switch (command) + { + case OUTPUT_OPEN: + { + ret = LinuxDvbOpen(context, (char *)argument); + break; + } + case OUTPUT_CLOSE: + { + ret = LinuxDvbClose(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PLAY: // 4 + { + sCURRENT_PTS = 0; + ret = LinuxDvbPlay(context, (char *)argument); + break; + } + case OUTPUT_STOP: + { + reset(context); + ret = LinuxDvbStop(context, (char *)argument); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_FLUSH: + { + ret = LinuxDvbFlush(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PAUSE: + { + ret = LinuxDvbPause(context, (char *)argument); + break; + } + case OUTPUT_CONTINUE: + { + ret = LinuxDvbContinue(context, (char *)argument); + break; + } + case OUTPUT_FASTFORWARD: + { + return LinuxDvbFastForward(context, (char *)argument); + break; + } + case OUTPUT_REVERSE: + { + return LinuxDvbReverse(context, (char *)argument); + break; + } + case OUTPUT_AVSYNC: + { + ret = LinuxDvbAVSync(context, (char *)argument); + break; + } + case OUTPUT_CLEAR: + { + ret = LinuxDvbClear(context, (char *)argument); + reset(context); + sCURRENT_PTS = 0; + break; + } + case OUTPUT_PTS: + { + unsigned long long int pts = 0; + ret = LinuxDvbPts(context, &pts); + *((unsigned long long int *)argument) = (unsigned long long int)pts; + break; + } + case OUTPUT_SWITCH: + { + ret = LinuxDvbSwitch(context, (char *)argument); + break; + } + case OUTPUT_SLOWMOTION: + { + return LinuxDvbSlowMotion(context, (char *)argument); + break; + } + case OUTPUT_AUDIOMUTE: + { + return LinuxDvbAudioMute(context, (char *)argument); + break; + } + case OUTPUT_DISCONTINUITY_REVERSE: + { + return LinuxDvbReverseDiscontinuity(context, (int *)argument); + break; + } + case OUTPUT_GET_FRAME_COUNT: + { + unsigned long long int frameCount = 0; + ret = LinuxDvbGetFrameCount(context, &frameCount); + *((unsigned long long int *)argument) = (unsigned long long int)frameCount; + break; + } + case OUTPUT_GET_PROGRESSIVE: + { + ret = cERR_LINUXDVB_NO_ERROR; + *((int *)argument) = videoInfo.progressive; + break; + } + default: + linuxdvb_err("ContainerCmd %d not supported!\n", command); + ret = cERR_LINUXDVB_ERROR; + break; + } + linuxdvb_printf(50, "exiting with value %d\n", ret); + return ret; +} + +static char *LinuxDvbCapabilities[] = { "audio", "video", NULL }; + +struct Output_s LinuxDvbOutput = +{ + "LinuxDvb", + &Command, + &Write, + LinuxDvbCapabilities +}; diff --git a/libeplayer3-arm/output/output.c b/libeplayer3-arm/output/output.c new file mode 100644 index 0000000..493435d --- /dev/null +++ b/libeplayer3-arm/output/output.c @@ -0,0 +1,560 @@ +/* + * Output handling. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include "common.h" +#include "output.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define OUTPUT_DEBUG +#else +#define OUTPUT_SILENT +#endif + +#ifdef OUTPUT_DEBUG + +static short debug_level = 0; + +#define output_printf(level, x...) do { \ + if (debug_level >= level) fprintf(stderr, x); } while (0) +#else +#define output_printf(level, x...) +#endif + +#ifndef OUTPUT_SILENT +#define output_err(x...) do { printf(x); } while (0) +#else +#define output_err(x...) +#endif + +/* Error Constants */ +#define cERR_OUTPUT_NO_ERROR 0 +#define cERR_OUTPUT_INTERNAL_ERROR -1 + +static const char *FILENAME = "output.c"; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Output_t *AvailableOutput[] = +{ + &LinuxDvbOutput, + &SubtitleOutput, + NULL +}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static void printOutputCapabilities() +{ + int i, j; + output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + output_printf(10, "Capabilities:\n"); + for (i = 0; AvailableOutput[i] != NULL; i++) + { + output_printf(10, "\t%s : ", AvailableOutput[i]->Name); + for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++) + { + output_printf(10, "%s ", AvailableOutput[i]->Capabilities[j]); + } + output_printf(10, "\n"); + } +} + +/* ***************************** */ +/* Output Functions */ +/* ***************************** */ + +static void OutputAdd(Context_t *context, char *port) +{ + int i, j; + output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + for (i = 0; AvailableOutput[i] != NULL; i++) + { + for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++) + { + if (!strcmp(AvailableOutput[i]->Capabilities[j], port)) + { + if (!strcmp("audio", port)) + { + context->output->audio = AvailableOutput[i]; + return; + } + else if (!strcmp("video", port)) + { + context->output->video = AvailableOutput[i]; + return; + } + else if (!strcmp("subtitle", port)) + { + context->output->subtitle = AvailableOutput[i]; + return; + } + } + } + } +} + +static void OutputDel(Context_t *context, char *port) +{ + output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + if (!strcmp("audio", port)) + { + context->output->audio = NULL; + } + else if (!strcmp("video", port)) + { + context->output->video = NULL; + } + else if (!strcmp("subtitle", port)) + { + context->output->subtitle = NULL; + } +} + +static int Command(void *_context, OutputCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_OUTPUT_NO_ERROR; + output_printf(10, "%s::%s Command %d\n", FILENAME, __FUNCTION__, command); + switch (command) + { + case OUTPUT_OPEN: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_OPEN, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_OPEN, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_OPEN, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_CLOSE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_CLOSE, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_CLOSE, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_CLOSE, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_ADD: + { + OutputAdd(context, (char *) argument); + break; + } + case OUTPUT_DEL: + { + OutputDel(context, (char *) argument); + break; + } + case OUTPUT_CAPABILITIES: + { + printOutputCapabilities(); + break; + } + case OUTPUT_PLAY: + { + // 4 + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret = context->output->video->Command(context, OUTPUT_PLAY, "video"); + } + // success or not executed, dunn care + if (!ret) + { + if (context->playback->isAudio) + { + ret = context->output->audio->Command(context, OUTPUT_PLAY, "audio"); + } + } + if (!ret) + { + if (context->playback->isSubtitle) + { + ret = context->output->subtitle->Command(context, OUTPUT_PLAY, "subtitle"); + } + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_STOP: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_STOP, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_STOP, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_STOP, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_FLUSH: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_FLUSH, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_FLUSH, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_FLUSH, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_PAUSE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_PAUSE, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_PAUSE, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_FASTFORWARD: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_FASTFORWARD, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_FASTFORWARD, "audio"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_REVERSE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_REVERSE, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_REVERSE, "audio"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_CONTINUE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_CONTINUE, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_CONTINUE, "audio"); + } + if (context->playback->isSubtitle) + { + ret |= context->output->subtitle->Command(context, OUTPUT_CONTINUE, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_AVSYNC: + { + if (context && context->playback) + { + if (context->playback->isVideo && context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_AVSYNC, "audio"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_CLEAR: + { + if (context && context->playback) + { + if (context->playback->isVideo && (argument == NULL || *(char *) argument == 'v')) + { + ret |= context->output->video->Command(context, OUTPUT_CLEAR, "video"); + } + if (context->playback->isAudio && (argument == NULL || *(char *) argument == 'a')) + { + ret |= context->output->audio->Command(context, OUTPUT_CLEAR, "audio"); + } + if (context->playback->isSubtitle && (argument == NULL || *(char *) argument == 's')) + { + ret |= context->output->subtitle->Command(context, OUTPUT_CLEAR, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_PTS: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + return context->output->video->Command(context, OUTPUT_PTS, argument); + } + if (context->playback->isAudio) + { + return context->output->audio->Command(context, OUTPUT_PTS, argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_SWITCH: + { + if (context && context->playback) + { + if (context->playback->isAudio) + { + return context->output->audio->Command(context, OUTPUT_SWITCH, "audio"); + } + if (context->playback->isVideo) + { + return context->output->video->Command(context, OUTPUT_SWITCH, "video"); + } + if (context->playback->isSubtitle) + { + return context->output->subtitle->Command(context, OUTPUT_SWITCH, "subtitle"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_SLOWMOTION: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_SLOWMOTION, "video"); + } + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_SLOWMOTION, "audio"); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_AUDIOMUTE: + { + if (context && context->playback) + { + if (context->playback->isAudio) + { + ret |= context->output->audio->Command(context, OUTPUT_AUDIOMUTE, (char *) argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_DISCONTINUITY_REVERSE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + ret |= context->output->video->Command(context, OUTPUT_DISCONTINUITY_REVERSE, (void *) argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_GET_FRAME_COUNT: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + return context->output->video->Command(context, OUTPUT_GET_FRAME_COUNT, argument); + } + if (context->playback->isAudio) + { + return context->output->audio->Command(context, OUTPUT_GET_FRAME_COUNT, argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + case OUTPUT_GET_PROGRESSIVE: + { + if (context && context->playback) + { + if (context->playback->isVideo) + { + return context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, (void *) argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + } + default: + output_err("%s::%s OutputCmd %d not supported!\n", FILENAME, __FUNCTION__, command); + ret = cERR_OUTPUT_INTERNAL_ERROR; + break; + } + output_printf(10, "%s::%s exiting with value %d\n", FILENAME, __FUNCTION__, ret); + return ret; +} + +OutputHandler_t OutputHandler = +{ + "Output", + NULL, //audio + NULL, //video + NULL, //subtitle + &Command +}; diff --git a/libeplayer3-arm/output/output_subtitle.c b/libeplayer3-arm/output/output_subtitle.c new file mode 100644 index 0000000..a88c4bc --- /dev/null +++ b/libeplayer3-arm/output/output_subtitle.c @@ -0,0 +1,332 @@ +/* + * Subtitle output to one registered client. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +//SULGE DEBUG ENABLED +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define SUBTITLE_DEBUG +#else +#define SUBTITLE_SILENT +#endif + +#ifdef SUBTITLE_DEBUG + +static short debug_level = 0; + +#define subtitle_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define subtitle_printf(level, fmt, x...) +#endif + +#ifndef SUBTITLE_SILENT +#define subtitle_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define subtitle_err(fmt, x...) +#endif + +/* Error Constants */ +#define cERR_SUBTITLE_NO_ERROR 0 +#define cERR_SUBTITLE_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* +Number, Style, Name,, MarginL, MarginR, MarginV, Effect,, Text + +1038,0,tdk,,0000,0000,0000,,That's not good. +1037,0,tdk,,0000,0000,0000,,{\i1}Rack them up, rack them up,{\i0}\N{\i1}rack them up.{\i0} [90] +1036,0,tdk,,0000,0000,0000,,Okay, rack them up. +*/ + +#define PUFFERSIZE 20 + +/* ***************************** */ +/* Types */ +/* ***************************** */ + + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static pthread_mutex_t mutex; +static int isSubtitleOpened = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static void getMutex(int line) +{ + subtitle_printf(100, "%d requesting mutex\n", line); + pthread_mutex_lock(&mutex); + subtitle_printf(100, "%d received mutex\n", line); +} + +static void releaseMutex(int line) +{ + pthread_mutex_unlock(&mutex); + subtitle_printf(100, "%d released mutex\n", line); +} + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static char *ass_get_text(char *str) +{ + // Events are stored in the Block in this order: + // ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text + // 91,0,Default,,0,0,0,,maar hij smaakt vast tof. + int i = 0; + char *p_str = str; + while (i < 8 && *p_str != '\0') + { + if (*p_str == ',') + i++; + p_str++; + } + // standardize hard break: '\N' -> '\n' + // http://docs.aegisub.org/3.2/ASS_Tags/ + char *p_newline = NULL; + while ((p_newline = strstr(p_str, "\\N")) != NULL) + * (p_newline + 1) = 'n'; + return p_str; +} + +static char *json_string_escape(char *str) +{ + static char tmp[2048]; + char *ptr1 = tmp; + char *ptr2 = str; + while (*ptr2 != '\0') + { + switch (*ptr2) + { + case '"': + *ptr1++ = '\\'; + *ptr1++ = '\"'; + break; + case '\\': + *ptr1++ = '\\'; + *ptr1++ = '\\'; + break; + case '\b': + *ptr1++ = '\\'; + *ptr1++ = 'b'; + break; + case '\f': + *ptr1++ = '\\'; + *ptr1++ = 'f'; + break; + case '\n': + *ptr1++ = '\\'; + *ptr1++ = 'n'; + break; + case '\r': + *ptr1++ = '\\'; + *ptr1++ = 'r'; + break; + case '\t': + *ptr1++ = '\\'; + *ptr1++ = 't'; + break; + default: + *ptr1++ = *ptr2; + break; + } + ++ptr2; + } + *ptr1 = '\0'; + return tmp; +} + +static int Flush() +{ + fprintf(stderr, "{\"s_f\":{\"r\":0}}\n"); + return cERR_SUBTITLE_NO_ERROR; +} + +static int Write(void *_context, void *data) +{ + Context_t *context = (Context_t *)_context; + char *Encoding = NULL; + SubtitleOut_t *out = NULL; + int32_t curtrackid = -1; + subtitle_printf(10, "\n"); + if (data == NULL) + { + subtitle_err("null pointer passed\n"); + return cERR_SUBTITLE_ERROR; + } + out = (SubtitleOut_t *) data; + context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid); + if (curtrackid != out->trackId) + { + Flush(); + } + context->manager->subtitle->Command(context, MANAGER_GETENCODING, &Encoding); + if (Encoding == NULL) + { + subtitle_err("encoding unknown\n"); + return cERR_SUBTITLE_ERROR; + } + subtitle_printf(20, "Encoding:%s Text:%s Len:%d\n", Encoding, (const char *) out->data, out->len); + if (!strncmp("S_TEXT/SUBRIP", Encoding, 13)) + { + fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%lld,\"e\":%lld,\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, json_string_escape((char *)out->data)); + } + else if (!strncmp("S_TEXT/ASS", Encoding, 10)) + { + fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%lld,\"e\":%lld,\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, ass_get_text((char *)out->data)); + } + else + { + subtitle_err("unknown encoding %s\n", Encoding); + return cERR_SUBTITLE_ERROR; + } + subtitle_printf(10, "<\n"); + return cERR_SUBTITLE_NO_ERROR; +} + +static int32_t subtitle_Open(Context_t *context __attribute__((unused))) +{ + uint32_t i = 0 ; + subtitle_printf(10, "\n"); + if (isSubtitleOpened == 1) + { + subtitle_err("already opened! ignoring\n"); + return cERR_SUBTITLE_ERROR; + } + getMutex(__LINE__); + isSubtitleOpened = 1; + releaseMutex(__LINE__); + subtitle_printf(10, "<\n"); + return cERR_SUBTITLE_NO_ERROR; +} + +static int32_t subtitle_Close(Context_t *context __attribute__((unused))) +{ + uint32_t i = 0 ; + subtitle_printf(10, "\n"); + getMutex(__LINE__); + isSubtitleOpened = 0; + releaseMutex(__LINE__); + subtitle_printf(10, "<\n"); + return cERR_SUBTITLE_NO_ERROR; +} + +static int Command(void *_context, OutputCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; + int ret = cERR_SUBTITLE_NO_ERROR; + subtitle_printf(50, "%d\n", command); + switch (command) + { + case OUTPUT_OPEN: + { + ret = subtitle_Open(context); + break; + } + case OUTPUT_CLOSE: + { + ret = subtitle_Close(context); + break; + } + case OUTPUT_PLAY: + { + break; + } + case OUTPUT_STOP: + { + break; + } + case OUTPUT_SWITCH: + { + ret = Flush(); + break; + } + case OUTPUT_FLUSH: + { + ret = Flush(); + break; + } + case OUTPUT_CLEAR: + { + ret = Flush(); + break; + } + case OUTPUT_PAUSE: + { + subtitle_err("Subtitle Pause not implemented\n"); + ret = cERR_SUBTITLE_ERROR; + break; + } + case OUTPUT_CONTINUE: + { + subtitle_err("Subtitle Continue not implemented\n"); + ret = cERR_SUBTITLE_ERROR; + break; + } + default: + subtitle_err("OutputCmd %d not supported!\n", command); + ret = cERR_SUBTITLE_ERROR; + break; + } + subtitle_printf(50, "exiting with value %d\n", ret); + return ret; +} + + +static char *SubtitleCapabilitis[] = { "subtitle", NULL }; + +Output_t SubtitleOutput = +{ + "Subtitle", + &Command, + &Write, + SubtitleCapabilitis +}; diff --git a/libeplayer3-arm/output/writer/common/misc.c b/libeplayer3-arm/output/writer/common/misc.c new file mode 100644 index 0000000..c9c18af --- /dev/null +++ b/libeplayer3-arm/output/writer/common/misc.c @@ -0,0 +1,123 @@ +/* + * LinuxDVB Output handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length) +{ + unsigned int bit_buf; + unsigned int bit_left; + bit_buf = ld->BitBuffer; + bit_left = ld->Remaining; +#ifdef DEBUG_PUTBITS + if (ld->debug) + dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n", code, length, bit_buf, bit_left); +#endif /* DEBUG_PUTBITS */ + if (length < bit_left) + { + /* fits into current buffer */ + bit_buf = (bit_buf << length) | code; + bit_left -= length; + } + else + { + /* doesn't fit */ + bit_buf <<= bit_left; + bit_buf |= code >> (length - bit_left); + ld->Ptr[0] = (char)(bit_buf >> 24); + ld->Ptr[1] = (char)(bit_buf >> 16); + ld->Ptr[2] = (char)(bit_buf >> 8); + ld->Ptr[3] = (char)bit_buf; + ld->Ptr += 4; + length -= bit_left; + bit_buf = code & ((1 << length) - 1); + bit_left = 32 - length; + bit_buf = code; + } +#ifdef DEBUG_PUTBITS + if (ld->debug) + dprintf("bit_left = %d, bit_buf = 0x%x\n", bit_left, bit_buf); +#endif /* DEBUG_PUTBITS */ + /* writeback */ + ld->BitBuffer = bit_buf; + ld->Remaining = bit_left; +} + +void FlushBits(BitPacker_t *ld) +{ + ld->BitBuffer <<= ld->Remaining; + while (ld->Remaining < 32) + { +#ifdef DEBUG_PUTBITS + if (ld->debug) + dprintf("flushing 0x%2.2x\n", ld->BitBuffer >> 24); +#endif /* DEBUG_PUTBITS */ + *ld->Ptr++ = ld->BitBuffer >> 24; + ld->BitBuffer <<= 8; + ld->Remaining += 8; + } + ld->Remaining = 32; + ld->BitBuffer = 0; +} diff --git a/libeplayer3-arm/output/writer/common/pes.c b/libeplayer3-arm/output/writer/common/pes.c new file mode 100644 index 0000000..93a18ad --- /dev/null +++ b/libeplayer3-arm/output/writer/common/pes.c @@ -0,0 +1,163 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +/* ***************************** */ +/* Types */ +/* ***************************** */ + + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +int32_t InsertVideoPrivateDataHeader(uint8_t *data, int32_t payload_size) +{ + BitPacker_t ld2 = {data, 0, 32}; + int32_t i = 0; + PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8); + PutBits(&ld2, payload_size & 0xff, 8); + PutBits(&ld2, (payload_size >> 8) & 0xff, 8); + PutBits(&ld2, (payload_size >> 16) & 0xff, 8); + for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++) + { + PutBits(&ld2, 0, 8); + } + FlushBits(&ld2); + return PES_PRIVATE_DATA_LENGTH + 1; +} + +int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t pts, int32_t pic_start_code) +{ + BitPacker_t ld2 = {data, 0, 32}; + if (size > (MAX_PES_PACKET_SIZE - 13)) + { + size = -1; // unbounded + } + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x1, 8); // Start Code + PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream + //4 + if (-1 == size) + { + PutBits(&ld2, 0x0, 16); + } + else + { + PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length + } + //6 = 4+2 + PutBits(&ld2, 0x2, 2); // 10 + PutBits(&ld2, 0x0, 2); // PES_Scrambling_control + PutBits(&ld2, 0x0, 1); // PES_Priority + PutBits(&ld2, 0x0, 1); // data_alignment_indicator + PutBits(&ld2, 0x0, 1); // Copyright + PutBits(&ld2, 0x0, 1); // Original or Copy + //7 = 6+1 + if (pts != INVALID_PTS_VALUE) + { + PutBits(&ld2, 0x2, 2); + } + else + { + PutBits(&ld2, 0x0, 2); // PTS_DTS flag + } + PutBits(&ld2, 0x0, 1); // ESCR_flag + PutBits(&ld2, 0x0, 1); // ES_rate_flag + PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag + PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag + PutBits(&ld2, 0x0, 1); // PES_CRC_flag + PutBits(&ld2, 0x0, 1); // PES_extension_flag + //8 = 7+1 + if (pts != INVALID_PTS_VALUE) + { + PutBits(&ld2, 0x5, 8); + } + else + { + PutBits(&ld2, 0x0, 8); // PES_header_data_length + } + //9 = 8+1 + if (pts != INVALID_PTS_VALUE) + { + PutBits(&ld2, 0x2, 4); + PutBits(&ld2, (pts >> 30) & 0x7, 3); + PutBits(&ld2, 0x1, 1); + PutBits(&ld2, (pts >> 15) & 0x7fff, 15); + PutBits(&ld2, 0x1, 1); + PutBits(&ld2, pts & 0x7fff, 15); + PutBits(&ld2, 0x1, 1); + } + //14 = 9+5 + if (pic_start_code) + { + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x1, 8); // Start Code + PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start + PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code) + //14 + 4 = 18 + } + FlushBits(&ld2); + return (ld2.Ptr - data); +} diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c new file mode 100644 index 0000000..5dc3931 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -0,0 +1,374 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "ffmpeg/latmenc.h" + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" +#include "aac.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +//#define SAM_WITH_DEBUG + +#ifdef SAM_WITH_DEBUG +#define AAC_DEBUG +#else +#define AAC_SILENT +#endif + +#ifdef AAC_DEBUG + +static short debug_level = 0; + +#define aac_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define aac_printf(level, fmt, x...) +#endif + +#ifndef AAC_SILENT +#define aac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define aac_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/// ** AAC ADTS format ** +/// +/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM +/// MMMMMMMM MMMNNNNN NNNNNNOO ........ +/// +/// Sign Length Position Description +/// +/// A 12 (31-20) Sync code +/// B 1 (19) ID +/// C 2 (18-17) layer +/// D 1 (16) protect absent +/// E 2 (15-14) profile +/// F 4 (13-10) sample freq index +/// G 1 (9) private +/// H 3 (8-6) channel config +/// I 1 (5) original/copy +/// J 1 (4) home +/// K 1 (3) copyright id +/// L 1 (2) copyright start +/// M 13 (1-0,31-21) frame length +/// N 11 (20-10) adts buffer fullness +/// O 2 (9-8) num of raw data blocks in frame + +/* +LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc +HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc +*/ + +/* +ADIF = basic format called Audio Data Interchange Format (ADIF) + consisting of a single header followed by the raw AAC audio data blocks +ADTS = streaming format called Audio Data Transport Stream (ADTS) + consisting of a series of frames, each frame having a header followed by the AAC audio data +LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format +*/ + +static unsigned char DefaultAACHeader[] = +{ + 0xff, + 0xf1, + /*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s + 0x80, //(Channels & 0x03) << 6; + 0x00, + 0x1f, + 0xfc +}; + +LATMContext *pLATMCtx = NULL; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + if (pLATMCtx) + { + free(pLATMCtx); + pLATMCtx = NULL; + } + return 0; +} + +static int _writeData(void *_call, int type) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n _writeData type[%d]\n", type); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len < 8)) + { + aac_err("parsing Data with missing AAC header. ignoring...\n"); + return 0; + } + /* simple validation */ + if (0 == type) // check ADTS header + { + if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1])) + { + aac_err("parsing Data with missing syncword. ignoring...\n"); + return 0; + } + } + else // check LOAS header + { + if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe && + (AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len)) + { + aac_err("parsing Data with wrong latm header. ignoring...\n"); + return 0; + } + } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev_with_retry(call->fd, iov, 2); +} + +static int writeDataADTS(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + aac_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + aac_err("file pointer < 0. ignoring ...\n"); + return 0; + } + if ((call->private_data && 0 == strncmp("ADTS", call->private_data, call->private_size)) || + HasADTSHeader(call->data, call->len)) + { + return _writeData(_call, 0); + } + uint32_t PacketLength = call->len + AAC_HEADER_LENGTH; + uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH]; + uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + uint8_t *pExtraData = &PesHeader[headerSize]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (call->private_data == NULL) + { + aac_printf(10, "private_data = NULL\n"); + memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH); + } + else + { + memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH); + } + pExtraData[3] &= 0xC0; + /* frame size over last 2 bits */ + pExtraData[3] |= (PacketLength & 0x1800) >> 11; + /* frame size continued over full byte */ + pExtraData[4] = (PacketLength & 0x1FF8) >> 3; + /* frame size continued first 3 bits */ + pExtraData[5] = (PacketLength & 7) << 5; + /* buffer fullness(0x7FF for VBR) over 5 last bits */ + pExtraData[5] |= 0x1F; + /* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for + * number of raw data blocks */ + pExtraData[6] = 0xFC; + //PesHeader[6] = 0x81; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize + AAC_HEADER_LENGTH; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev_with_retry(call->fd, iov, 2); +} + +static int writeDataLATM(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + aac_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->private_data && 0 == strncmp("LATM", call->private_data, call->private_size)) + { + return _writeData(_call, 1); + } + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (!pLATMCtx) + { + pLATMCtx = malloc(sizeof(LATMContext)); + memset(pLATMCtx, 0x00, sizeof(LATMContext)); + pLATMCtx->mod = 14; + pLATMCtx->counter = 0; + } + if (!pLATMCtx) + { + aac_err("parsing NULL pLATMCtx. ignoring...\n"); + return 0; + } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); + if (ret) + { + printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ + (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + aac_err("latm_decode_extradata failed. ignoring...\n"); + return 0; + } + ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size); + if (ret) + { + aac_err("latm_write_packet failed. ignoring...\n"); + return 0; + } + unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[3]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = pLATMCtx->loas_header; + iov[1].iov_len = 3; + iov[2].iov_base = pLATMCtx->buffer; + iov[2].iov_len = pLATMCtx->len; + return writev_with_retry(call->fd, iov, 3); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "aac", + eAudio, + "A_AAC", + -1, + AUDIOTYPE_AAC_PLUS, + -1 +}; + +struct Writer_s WriterAudioAAC = +{ + &reset, + &writeDataADTS, + NULL, + &caps +}; + +static WriterCaps_t caps_aac_latm = +{ + "aac", + eAudio, + "A_AAC_LATM", + -1, + AUDIOTYPE_AAC_HE, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM + -1 +}; + +struct Writer_s WriterAudioAACLATM = +{ + &reset, + &writeDataLATM, + NULL, + &caps_aac_latm +}; + +static WriterCaps_t caps_aacplus = +{ + "aac", + eAudio, + "A_AAC_PLUS", + -1, + AUDIOTYPE_AAC_PLUS, + -1 +}; + +struct Writer_s WriterAudioAACPLUS = +{ + &reset, + &writeDataADTS, + NULL, + &caps_aacplus +}; \ No newline at end of file diff --git a/libeplayer3-arm/output/writer/mipsel/ac3.c b/libeplayer3-arm/output/writer/mipsel/ac3.c new file mode 100644 index 0000000..39b7cc7 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/ac3.c @@ -0,0 +1,170 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define AC3_HEADER_LENGTH 7 + +#define AC3_DEBUG + +#ifdef AC3_DEBUG + +static short debug_level = 0; + +#define ac3_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ac3_printf(level, fmt, x...) +#endif + +#ifndef AC3_SILENT +#define ac3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ac3_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +unsigned char AC3_SYNC_HEADER[] = {0x80, 0x01, 0x00, 0x01}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + ac3_printf(10, "\n"); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if (call == NULL) + { + ac3_err("call data is NULL...\n"); + return 0; + } + ac3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + ac3_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + ac3_err("file pointer < 0. ignoring ...\n"); + return 0; + } + struct iovec iov[3]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); //+ sizeof(AC3_SYNC_HEADER) + //PesHeader[6] = 0x81; + //PesHeader[7] = 0x80; + //PesHeader[8] = 0x09; + //iov[1].iov_base = AC3_SYNC_HEADER; + //iov[1].iov_len = sizeof(AC3_SYNC_HEADER); + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + ac3_printf(40, "PES HEADER LEN %d\n", iov[0].iov_len); + return writev_with_retry(call->fd, iov, 2); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_ac3 = +{ + "ac3", + eAudio, + "A_AC3", + AUDIO_ENCODING_AC3, + AUDIOTYPE_AC3, + -1 +}; + +struct Writer_s WriterAudioAC3 = +{ + &reset, + &writeData, + NULL, + &caps_ac3 +}; + +static WriterCaps_t caps_eac3 = +{ + "ac3", + eAudio, + "A_EAC3", + AUDIO_ENCODING_AC3, + AUDIOTYPE_AC3_PLUS, + -1 +}; + +struct Writer_s WriterAudioEAC3 = +{ + &reset, + &writeData, + NULL, + &caps_eac3 +}; diff --git a/libeplayer3-arm/output/writer/mipsel/amr.c b/libeplayer3-arm/output/writer/mipsel/amr.c new file mode 100644 index 0000000..fc0676a --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/amr.c @@ -0,0 +1,176 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define AMR_DEBUG +#else +#define AMR_SILENT +#endif + +#ifdef AMR_DEBUG + +static short debug_level = 0; + +#define amr_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define amr_printf(level, fmt, x...) +#endif + +#ifndef AMR_SILENT +#define amr_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define amr_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4 + 9]; + amr_printf(10, "\n"); + if (call == NULL) + { + amr_err("call data is NULL...\n"); + return 0; + } + amr_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + amr_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + amr_err("file pointer < 0. ignoring ...\n"); + return 0; + } + uint8_t hasCodecData = 1; + if (NULL != call->private_data && call->private_size >= 17) + { + amr_err("wrong private_data. ignoring ...\n"); + hasCodecData = 1; + } + size_t payload_len = call->len; + if (hasCodecData) + { + payload_len += 9; + } + payload_len += 4; + uint32_t headerSize = InsertPesHeader(PesHeader, payload_len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + PesHeader[headerSize++] = (payload_len >> 24) & 0xff; + PesHeader[headerSize++] = (payload_len >> 16) & 0xff; + PesHeader[headerSize++] = (payload_len >> 8) & 0xff; + PesHeader[headerSize++] = payload_len & 0xff; + if (hasCodecData) + { + uint8_t tmp[] = {0x45, 0x4d, 0x50, 0x20, 0x00, 0x00, 0x80, 0x00, 0x01}; + memcpy(&PesHeader[headerSize], tmp, 9); + //memcpy(&PesHeader[headerSize], call->private_data + 8, 9); + //memset(&PesHeader[headerSize], 0, 9); + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + int len = writev_with_retry(call->fd, iov, 2); + amr_printf(10, "amr_Write-< len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_amr = +{ + "amr", + eAudio, + "A_AMR", + -1, + AUDIOTYPE_AMR, + -1 +}; + +struct Writer_s WriterAudioAMR = +{ + &reset, + &writeData, + NULL, + &caps_amr +}; + + diff --git a/libeplayer3-arm/output/writer/mipsel/divx3.c b/libeplayer3-arm/output/writer/mipsel/divx3.c new file mode 100644 index 0000000..20a867a --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/divx3.c @@ -0,0 +1,196 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define B_GET_BITS(w,e,b) (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b)))) +#define B_SET_BITS(name,v,e,b) (((unsigned)(v))<<(b)) + + +#ifdef SAM_WITH_DEBUG +#define DIVX_DEBUG +#else +#define DIVX_SILENT +#endif + +#ifdef DIVX_DEBUG + +static short debug_level = 0; + +#define divx_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_printf(level, fmt, x...) +#endif + +#ifndef DIVX_SILENT +#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static uint8_t initialHeader = 1; +static uint8_t brcm_divx311_sequence_header[] = +{ + 0x00, 0x00, 0x01, 0xE0, 0x00, 0x34, 0x80, 0x80, // PES HEADER + 0x05, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, /* 0 .. 7 */ + 0x08, 0xC8, 0x0D, 0x40, 0x00, 0x53, 0x88, 0x40, /* 8 .. 15 */ + 0x0C, 0x40, 0x01, 0x90, 0x00, 0x97, 0x53, 0x0A, /* 16 .. 24 */ + 0x00, 0x00, 0x00, 0x00, + 0x30, 0x7F, 0x00, 0x00, 0x01, 0xB2, 0x44, 0x69, /* 0 .. 7 */ + 0x76, 0x58, 0x33, 0x31, 0x31, 0x41, 0x4E, 0x44 /* 8 .. 15 */ +}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4]; + unsigned char Version = 5; + unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE; + divx_printf(10, "\n"); + if (call == NULL) + { + divx_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + divx_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + divx_err("file pointer < 0. ignoring ...\n"); + return 0; + } + divx_printf(10, "AudioPts %lld\n", call->Pts); + struct iovec iov[8]; + int ic = 0; + if (initialHeader) + { + initialHeader = 0; + uint8_t *data = brcm_divx311_sequence_header; + int32_t height = call->Height; + int32_t width = call->Width; + data += 38; + data[0] = B_GET_BITS(width, 11, 4); + data[1] = B_SET_BITS("width [3..0]", B_GET_BITS(width, 3, 0), 7, 4) | + B_SET_BITS("'10'", 0x02, 3, 2) | + B_SET_BITS("height [11..10]", B_GET_BITS(height, 11, 10), 1, 0); + data[2] = B_GET_BITS(height, 9, 2); + data[3] = B_SET_BITS("height [1.0]", B_GET_BITS(height, 1, 0), 7, 6) | + B_SET_BITS("'100000'", 0x20, 5, 0); + iov[ic].iov_base = brcm_divx311_sequence_header; + iov[ic++].iov_len = sizeof(brcm_divx311_sequence_header); + } + iov[ic].iov_base = PesHeader; + uint32_t headerSize = 0; + if (memcmp(call->data, "\x00\x00\x01\xb6", 4)) + { + headerSize = InsertPesHeader(PesHeader, call->len + 4, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + memcpy(PesHeader + headerSize, "\x00\x00\x01\xb6", 4); + headerSize += 4; + } + else + { + headerSize = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + } + iov[ic++].iov_len = headerSize; + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + int len = writev_with_retry(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t divix3_caps = +{ + "divix3", + eVideo, + "V_DIVX3", + VIDEO_ENCODING_MPEG4P2, + STREAMTYPE_DIVX311, + -1 +}; + +struct Writer_s WriterVideoDIVX3 = +{ + &reset, + &writeData, + NULL, + &divix3_caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/dts.c b/libeplayer3-arm/output/writer/mipsel/dts.c new file mode 100644 index 0000000..fa5103f --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/dts.c @@ -0,0 +1,178 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size. +#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE) +#define PES_AUDIO_PACKET_SIZE 2028 +#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples. + +#ifdef SAM_WITH_DEBUG +#define DTS_DEBUG +#else +#define DTS_SILENT +#endif + +#ifdef DTS_DEBUG + +static int16_t debug_level = 0; + +#define dts_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define dts_printf(level, fmt, x...) +#endif + +#ifndef DTS_SILENT +#define dts_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define dts_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int32_t reset() +{ + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_AUDIO_HEADER_SIZE]; + dts_printf(10, "\n"); + if (call == NULL) + { + dts_err("call data is NULL...\n"); + return 0; + } + dts_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + dts_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + dts_err("file pointer < 0. ignoring ...\n"); + return 0; + } + uint8_t *Data = call->data; + int32_t Size = call->len; +#ifdef CHECK_FOR_DTS_HD + int32_t pos = 0; + while ((pos + 4) <= Size) + { + // check for DTS-HD + if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25")) + { + Size = pos; + break; + } + ++pos; + } +#endif +// #define DO_BYTESWAP +#ifdef DO_BYTESWAP + /* 16-bit byte swap all data before injecting it */ + for (i = 0; i < Size; i += 2) + { + uint8_t Tmp = Data[i]; + Data[i] = Data[i + 1]; + Data[i + 1] = Tmp; + } +#endif + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + iov[1].iov_base = Data; + iov[1].iov_len = Size; + int32_t len = writev_with_retry(call->fd, iov, 2); + dts_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "dts", + eAudio, + "A_DTS", + AUDIO_ENCODING_DTS, + AUDIOTYPE_DTS, + -1 +}; + +struct Writer_s WriterAudioDTS = +{ + &reset, + &writeData, + NULL, + &caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/h263.c b/libeplayer3-arm/output/writer/mipsel/h263.c new file mode 100644 index 0000000..9e6c32e --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/h263.c @@ -0,0 +1,171 @@ +/* + * linuxdvb output/writer handling. + * + * crow 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define H263_DEBUG + +#ifdef H263_DEBUG + +static short debug_level = 0; + +#define h263_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h263_printf(level, fmt, x...) +#endif + +#ifndef H263_SILENT +#define h263_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h263_err(fmt, x...) +#endif +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int32_t reset() +{ + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_MAX_HEADER_SIZE]; + int32_t len = 0; + h263_printf(10, "\n"); + if (call == NULL) + { + h263_err("call data is NULL...\n"); + return 0; + } + h263_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + h263_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h263_err("file pointer < 0. ignoring ...\n"); + return 0; + } + int32_t HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + int32_t PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len); + int32_t PesLength = PesHeader[PES_LENGTH_BYTE_0] + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength; + PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff; + PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; + PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; + PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; + HeaderLength += PrivateHeaderLength; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + len = writev_with_retry(call->fd, iov, 2); + h263_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_h263 = +{ + "h263", + eVideo, + "V_H263", + VIDEO_ENCODING_H263, + STREAMTYPE_H263, + CT_MPEG4_PART2 +}; + +struct Writer_s WriterVideoH263 = +{ + &reset, + &writeData, + NULL, + &caps_h263 +}; + +static WriterCaps_t caps_flv = +{ + "FLV", + eVideo, + "V_FLV", + VIDEO_ENCODING_FLV1, + STREAMTYPE_H263, + CT_MPEG4_PART2 +}; + +struct Writer_s WriterVideoFLV = +{ + &reset, + &writeData, + NULL, + &caps_flv +}; diff --git a/libeplayer3-arm/output/writer/mipsel/h264.c b/libeplayer3-arm/output/writer/mipsel/h264.c new file mode 100644 index 0000000..d2bcbcf --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/h264.c @@ -0,0 +1,441 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define H264_DEBUG +#ifdef H264_DEBUG + +static short debug_level = 0; + +#define h264_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_printf(level, fmt, x...) +#endif + +#ifndef H264_SILENT +#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_err(fmt, x...) +#endif + +#define IOVEC_SIZE 128 + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static unsigned char Head[] = {0, 0, 0, 1}; +static int initialHeader = 1; +static unsigned int NalLengthBytes = 1; +static unsigned char *CodecData = NULL; +static unsigned int CodecDataLen = 0; +static int avc3 = 0; +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771 +static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize) +{ + uint8_t *aExtraData = *ppExtraData; + if (aExtraData[0] != 1 || !pData) + { + // Not AVCC or nothing to update with. + return -1; + } + int32_t nalsize = (aExtraData[4] & 3) + 1; + uint8_t sps[256]; + uint8_t spsIdx = 0; + uint8_t numSps = 0; + uint8_t pps[256]; + uint8_t ppsIdx = 0; + uint8_t numPps = 0; + if (nalsize != 4) + { + return -1; + } + // Find SPS and PPS NALUs in AVCC data + uint8_t *d = pData; + while (d + 4 < pData + dataSize) + { + uint32_t nalLen = ReadUint32(d); + uint8_t nalType = d[4] & 0x1f; + if (nalType == 7) + { + /* SPS */ + // 16 bits size + sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); + sps[spsIdx++] = (uint8_t)(0xFF & nalLen); + if (spsIdx + nalLen >= sizeof(sps)) + { + h264_err("SPS no free space to copy...\n"); + return -1; + } + memcpy(&(sps[spsIdx]), d + 4, nalLen); + spsIdx += nalLen; + numSps += 1; + h264_printf(10, "SPS len[%u]...\n", nalLen); + } + else if (nalType == 8) + { + /* PPS */ + // 16 bits size + pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); + pps[ppsIdx++] = (uint8_t)(0xFF & nalLen); + if (ppsIdx + nalLen >= sizeof(sps)) + { + h264_err("PPS not free space to copy...\n"); + return -1; + } + memcpy(&(pps[ppsIdx]), d + 4, nalLen); + ppsIdx += nalLen; + numPps += 1; + h264_printf(10, "PPS len[%u]...\n", nalLen); + } + d += 4 + nalLen; + } + uint32_t idx = 0; + *ppExtraData = malloc(7 + spsIdx + ppsIdx); + aExtraData = *ppExtraData; + aExtraData[idx++] = 0x1; // version + aExtraData[idx++] = sps[3]; // profile + aExtraData[idx++] = sps[4]; // profile compat + aExtraData[idx++] = sps[5]; // level + aExtraData[idx++] = 0xff; // nal size - 1 + aExtraData[idx++] = 0xe0 | numSps; + if (numSps) + { + memcpy(&(aExtraData[idx]), sps, spsIdx); + idx += spsIdx; + } + aExtraData[idx++] = numPps; + if (numPps) + { + memcpy(&(aExtraData[idx]), pps, ppsIdx); + idx += ppsIdx; + } + h264_printf(10, "aExtraData len[%u]...\n", idx); + *pExtraDataSize = idx; + return 0; +} + +static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength) +{ + h264_printf(10, "H264 check codec data..!\n"); + int32_t ret = -100; + if (data) + { + unsigned char tmp[2048]; + unsigned int tmp_len = 0; + unsigned int cd_pos = 0; + h264_printf(10, "H264 have codec data..!\n"); + if (cd_len > 7 && data[0] == 1) + { + unsigned short len = (data[6] << 8) | data[7]; + if (cd_len >= (len + 8)) + { + unsigned int i = 0; + uint8_t profile_num[] = { 66, 77, 88, 100 }; + uint8_t profile_cmp[2] = { 0x67, 0x00 }; + const char *profile_str[] = { "baseline", "main", "extended", "high" }; + memcpy(tmp, Head, sizeof(Head)); + tmp_len += 4; + memcpy(tmp + tmp_len, data + 8, len); + for (i = 0; i < 4; ++i) + { + profile_cmp[1] = profile_num[i]; + if (!memcmp(tmp + tmp_len, profile_cmp, 2)) + { + uint8_t level_org = tmp[tmp_len + 3]; + if (level_org > 0x29) + { + h264_printf(10, "H264 %s profile@%d.%d patched down to 4.1!", profile_str[i], level_org / 10, level_org % 10); + tmp[tmp_len + 3] = 0x29; // level 4.1 + } + else + { + h264_printf(10, "H264 %s profile@%d.%d", profile_str[i], level_org / 10, level_org % 10); + } + break; + } + } + tmp_len += len; + cd_pos = 8 + len; + if (cd_len > (cd_pos + 2)) + { + len = (data[cd_pos + 1] << 8) | data[cd_pos + 2]; + cd_pos += 3; + if (cd_len >= (cd_pos + len)) + { + memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4); + tmp_len += 4; + memcpy(tmp + tmp_len, data + cd_pos, len); + tmp_len += len; + CodecData = malloc(tmp_len); + memcpy(CodecData, tmp, tmp_len); + CodecDataLen = tmp_len; + *NalLength = (data[4] & 0x03) + 1; + ret = 0; + } + else + { + h264_printf(10, "codec_data too short(4)"); + ret = -4; + } + } + else + { + h264_printf(10, "codec_data too short(3)"); + ret = -3; + } + } + else + { + h264_printf(10, "codec_data too short(2)"); + ret = -2; + } + } + else if (cd_len <= 7) + { + h264_printf(10, "codec_data too short(1)"); + ret = -1; + } + else + { + h264_printf(10, "wrong avcC version %d!", data[0]); + } + } + else + { + *NalLength = 0; + } + return ret; +} + +static int reset() +{ + initialHeader = 1; + avc3 = 0; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + unsigned long long int VideoPts; + unsigned int TimeDelta; + unsigned int TimeScale; + int len = 0; + int ic = 0; + struct iovec iov[IOVEC_SIZE]; + h264_printf(20, "\n"); + if (call == NULL) + { + h264_err("call data is NULL...\n"); + return 0; + } + TimeDelta = call->FrameRate; + TimeScale = call->FrameScale; + VideoPts = call->Pts; + h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) + { + h264_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h264_err("file pointer < 0. ignoring ...\n"); + return 0; + } + /* AnnexA */ + if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) || + (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || + (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)))) + { + uint32_t PacketLength = 0; + uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; + initialHeader = 0; + //if (initialHeader) // some rtsp streams can update codec data at runtime + { + initialHeader = 0; + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + PacketLength += call->private_size; + } + iov[ic].iov_base = ""; + iov[ic++].iov_len = 1; + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); + return writev_with_retry(call->fd, iov, ic); + } + else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0]) + { + h264_err("No valid private data available! [%d]\n", (int)call->private_size); + return 0; + } + uint32_t PacketLength = 0; + ic = 0; + iov[ic++].iov_base = PesHeader; + if (initialHeader) + { + if (CodecData) + { + free(CodecData); + CodecData = NULL; + } + uint8_t *private_data = call->private_data; + uint32_t private_size = call->private_size; + if (PreparCodecData(private_data, private_size, &NalLengthBytes)) + { + UpdateExtraData(&private_data, &private_size, call->data, call->len); + PreparCodecData(private_data, private_size, &NalLengthBytes); + } + if (private_data != call->private_data) + { + avc3 = 1; + free(private_data); + private_data = NULL; + } + if (CodecData != NULL) + { + iov[ic].iov_base = CodecData; + iov[ic++].iov_len = CodecDataLen; + PacketLength += CodecDataLen; + initialHeader = 0; + } + } + if (CodecData != NULL) + { + uint32_t pos = 0; + do + { + if (ic >= IOVEC_SIZE) + { + h264_err(">> Drop data due to ic overflow\n"); + break; + } + uint32_t pack_len = 0; + uint32_t i = 0; + for (i = 0; i < NalLengthBytes; i++, pos++) + { + pack_len <<= 8; + pack_len += call->data[pos]; + } + if ((pos + pack_len) > call->len) + { + pack_len = call->len - pos; + } + iov[ic].iov_base = Head; + iov[ic++].iov_len = sizeof(Head); + PacketLength += sizeof(Head); + iov[ic].iov_base = call->data + pos; + iov[ic++].iov_len = pack_len; + PacketLength += pack_len; + pos += pack_len; + } + while ((pos + NalLengthBytes) < call->len); + h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + len = writev_with_retry(call->fd, iov, ic); + PacketLength += iov[0].iov_len; + if (PacketLength != len) + { + h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength); + } + } + h264_printf(10, "< len %d\n", len); + return len; +} + +static int writeReverseData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + return 0; +} +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "h264", + eVideo, + "V_MPEG4/ISO/AVC", + VIDEO_ENCODING_H264, + STREAMTYPE_MPEG4_H264, + CT_H264 +}; + +struct Writer_s WriterVideoH264 = +{ + &reset, + &writeData, + &writeReverseData, + &caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/h265.c b/libeplayer3-arm/output/writer/mipsel/h265.c new file mode 100644 index 0000000..b0d07b2 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/h265.c @@ -0,0 +1,310 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define H265_DEBUG +#ifdef H265_DEBUG + +static short debug_level = 10; + +#define h264_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_printf(level, fmt, x...) +#endif + +#ifndef H265_SILENT +#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_err(fmt, x...) +#endif + +#define IOVEC_SIZE 128 + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static unsigned char Head[] = {0, 0, 0, 1}; +static int initialHeader = 1; +static unsigned int NalLengthBytes = 1; +static unsigned char *CodecData = NULL; +static unsigned int CodecDataLen = 0; +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength) +{ + h264_printf(10, "H265 check codec data..!\n"); + int32_t ret = -100; + if (data) + { + unsigned char tmp[2048]; + unsigned int tmp_len = 0; + h264_printf(10, "H265 have codec data..!"); + if (cd_len > 3 && (data[0] || data[1] || data[2] > 1)) + { + if (cd_len > 22) + { + int i; + if (data[0] != 0) + { + h264_printf(10, "Unsupported extra data version %d, decoding may fail", (int)data[0]); + } + *NalLength = (data[21] & 3) + 1; + int num_param_sets = data[22]; + int pos = 23; + for (i = 0; i < num_param_sets; i++) + { + int j; + if (pos + 3 > cd_len) + { + h264_printf(10, "Buffer underrun in extra header (%d >= %u)", pos + 3, cd_len); + break; + } + // ignore flags + NAL type (1 byte) + int nal_count = data[pos + 1] << 8 | data[pos + 2]; + pos += 3; + for (j = 0; j < nal_count; j++) + { + if (pos + 2 > cd_len) + { + h264_printf(10, "Buffer underrun in extra nal header (%d >= %u)", pos + 2, cd_len); + break; + } + int nal_size = data[pos] << 8 | data[pos + 1]; + pos += 2; + if (pos + nal_size > cd_len) + { + h264_printf(10, "Buffer underrun in extra nal (%d >= %u)", pos + 2 + nal_size, cd_len); + break; + } + memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4); + tmp_len += 4; + memcpy(tmp + tmp_len, data + pos, nal_size); + tmp_len += nal_size; + pos += nal_size; + } + } + CodecData = malloc(tmp_len); + memcpy(CodecData, tmp, tmp_len); + CodecDataLen = tmp_len; + } + } + } + else + { + *NalLength = 0; + } + return ret; +} + +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + unsigned long long int VideoPts; + unsigned int TimeDelta; + unsigned int TimeScale; + int len = 0; + int ic = 0; + struct iovec iov[IOVEC_SIZE]; + h264_printf(20, "\n"); + if (call == NULL) + { + h264_err("call data is NULL...\n"); + return 0; + } + TimeDelta = call->FrameRate; + TimeScale = call->FrameScale; + VideoPts = call->Pts; + h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) + { + h264_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h264_err("file pointer < 0. ignoring ...\n"); + return 0; + } + if (call->InfoFlags & 0x1) // TS container + { + h264_printf(10, "H265 simple inject method!\n"); + uint32_t PacketLength = 0; + uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; + initialHeader = 0; + if (initialHeader) + { + initialHeader = 0; + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + PacketLength += call->private_size; + } + iov[ic].iov_base = ""; + iov[ic++].iov_len = 1; + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); + return writev_with_retry(call->fd, iov, ic); + } + uint32_t PacketLength = 0; + ic = 0; + iov[ic++].iov_base = PesHeader; + if (initialHeader) + { + if (CodecData) + { + free(CodecData); + CodecData = NULL; + } + uint8_t *private_data = call->private_data; + uint32_t private_size = call->private_size; + PreparCodecData(private_data, private_size, &NalLengthBytes); + if (CodecData != NULL) + { + iov[ic].iov_base = CodecData; + iov[ic++].iov_len = CodecDataLen; + PacketLength += CodecDataLen; + initialHeader = 0; + } + } + if (CodecData != NULL) + { + uint32_t pos = 0; + do + { + if (ic >= IOVEC_SIZE) + { + h264_err(">> Drop data due to ic overflow\n"); + break; + } + uint32_t pack_len = 0; + uint32_t i = 0; + for (i = 0; i < NalLengthBytes; i++, pos++) + { + pack_len <<= 8; + pack_len += call->data[pos]; + } + if ((pos + pack_len) > call->len) + { + pack_len = call->len - pos; + } + iov[ic].iov_base = Head; + iov[ic++].iov_len = sizeof(Head); + PacketLength += sizeof(Head); + iov[ic].iov_base = call->data + pos; + iov[ic++].iov_len = pack_len; + PacketLength += pack_len; + pos += pack_len; + } + while ((pos + NalLengthBytes) < call->len); + h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + len = writev_with_retry(call->fd, iov, ic); + PacketLength += iov[0].iov_len; + if (PacketLength != len) + { + h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength); + } + } + h264_printf(10, "< len %d\n", len); + return len; +} + +static int writeReverseData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + return 0; +} +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "h265", + eVideo, + "V_HEVC", + -1, + STREAMTYPE_MPEG4_H265, + CT_H265 +}; + +struct Writer_s WriterVideoH265 = +{ + &reset, + &writeData, + &writeReverseData, + &caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/lpcm.c b/libeplayer3-arm/output/writer/mipsel/lpcm.c new file mode 100644 index 0000000..5030177 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/lpcm.c @@ -0,0 +1,266 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#define _XOPEN_SOURCE +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" +#include "pcm.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define LPCM_DEBUG +#else +#define LPCM_SILENT +#endif + +#ifdef LPCM_DEBUG + +static uint16_t debug_level = 1; + +#define lpcm_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define lpcm_printf(level, fmt, x...) +#endif + +#ifndef LPCM_SILENT +#define lpcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define lpcm_err(fmt, x...) +#endif + +#define LLPCM_VOB_HEADER_LEN (6) + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static uint8_t PesHeader[PES_MAX_HEADER_SIZE]; +static uint8_t initialHeader = 1; + +static uint8_t i_freq_code = 0; +static int32_t i_frame_samples; +static int32_t i_frame_size; +static int32_t i_buffer_used; +static int32_t i_frame_num; +static int32_t i_bitspersample; +static uint8_t *p_buffer = 0; +static uint8_t *p_frame_buffer = 0; +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +/* https://www.videolan.org/developers/vlc/modules/codec/lpcm.c + * LPCM DVD header : + * - number of frames in this packet (8 bits) + * - first access unit (16 bits) == 0x0003 ? + * - emphasis (1 bit) + * - mute (1 bit) + * - reserved (1 bit) + * - current frame (5 bits) + * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal + * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz + * - reserved (1 bit) + * - number of channels - 1 (3 bits) 1 == 2 channels + * - dynamic range (8 bits) 0x80 == neutral + */ + +static int32_t reset() +{ + initialHeader = 1; + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + lpcm_printf(10, "\n"); + if (!call) + { + lpcm_err("call data is NULL...\n"); + return 0; + } + lpcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) + { + lpcm_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + lpcm_err("file pointer < 0. ignoring ...\n"); + return 0; + } + pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; + int32_t i_rate = (int32_t)pcmPrivateData->sample_rate; + int32_t i_channels = (int32_t)pcmPrivateData->channels; + int32_t i_nb_samples = call->len / (i_channels * 2); + int32_t i_ret_size = 0; + if (i_channels > 8) + { + lpcm_err("Error DVD LPCM supports a maximum of eight channels i_channels[%d]\n", i_channels); + return 0; + } + if (pcmPrivateData->bResampling || NULL == p_buffer) + { + lpcm_printf(1, "i_rate: [%d]\n", i_rate); + lpcm_printf(1, "i_channels: [%d]\n", i_channels); + switch (i_rate) + { + case 48000: + i_freq_code = 0; + break; + case 96000: + i_freq_code = 1; + break; + case 44100: + i_freq_code = 2; + break; + case 32000: + i_freq_code = 3; + break; + default: + lpcm_err("Error DVD LPCM sample_rate not supported [%d]\n", i_rate); + return 0; + } + /* In DVD LCPM, a frame is always 150 PTS ticks. */ + i_frame_samples = i_rate * 150 / 90000; + i_frame_size = i_frame_samples * i_channels * 2 + LLPCM_VOB_HEADER_LEN; + if (NULL != p_buffer) + { + free(p_buffer); + } + p_buffer = malloc(i_frame_samples * i_channels * 16); + if (NULL != p_frame_buffer) + { + free(p_frame_buffer); + } + p_frame_buffer = malloc(i_frame_size); + i_buffer_used = 0; + i_frame_num = 0; + i_bitspersample = 16; + } + const int i_num_frames = (i_buffer_used + i_nb_samples) / i_frame_samples; + const int i_leftover_samples = (i_buffer_used + i_nb_samples) % i_frame_samples; + const int i_start_offset = -i_buffer_used; + int32_t i_bytes_consumed = 0; + int32_t i = 0; + for (i = 0; i < i_num_frames; ++i) + { + uint8_t *frame = (uint8_t *)p_frame_buffer; + frame[0] = 1; /* one frame in packet */ + frame[1] = 0; + frame[2] = 0; /* no first access unit */ + frame[3] = (i_frame_num + i) & 0x1f; /* no emphasis, no mute */ + frame[4] = (i_freq_code << 4) | (i_channels - 1); + frame[5] = 0x80; /* neutral dynamic range */ + const int i_consume_samples = i_frame_samples - i_buffer_used; + const int i_kept_bytes = i_buffer_used * i_channels * 2; + const int i_consume_bytes = i_consume_samples * i_channels * 2; +#ifdef WORDS_BIGENDIAN + memcpy(frame + 6, p_buffer, i_kept_bytes); + memcpy(frame + 6 + i_kept_bytes, call->data + i_bytes_consumed, i_consume_bytes); +#else + swab(p_buffer, frame + 6, i_kept_bytes); + swab(call->data + i_bytes_consumed, frame + 6 + i_kept_bytes, i_consume_bytes); +#endif + i_frame_num++; + i_buffer_used = 0; + i_bytes_consumed += i_consume_bytes; + /* We need to find i_length by means of next_pts due to possible roundoff errors. */ + uint64_t this_pts = call->Pts + (i * i_frame_samples + i_start_offset) * 90000 / i_rate; + uint32_t pes_header_size = 0; + pes_header_size = InsertPesHeader(PesHeader, i_frame_size + 1, MPEG_AUDIO_PES_START_CODE, this_pts, 0); + PesHeader[pes_header_size] = 0xa0; + pes_header_size += 1; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = pes_header_size; + iov[1].iov_base = frame; + iov[1].iov_len = i_frame_size; + i_ret_size += writev_with_retry(call->fd, iov, 2); + } + memcpy(p_buffer, call->data + i_bytes_consumed, i_leftover_samples * i_channels * 2); + i_buffer_used = i_leftover_samples; + return i_ret_size; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_lpcm = +{ + "ipcm", + eAudio, + "A_LPCM", + AUDIO_ENCODING_LPCMA, + AUDIOTYPE_LPCM, + -1 +}; + +struct Writer_s WriterAudioLPCM = +{ + &reset, + &writeData, /* writeDataLPCM */ + NULL, + &caps_lpcm +}; diff --git a/libeplayer3-arm/output/writer/mipsel/mp3.c b/libeplayer3-arm/output/writer/mipsel/mp3.c new file mode 100644 index 0000000..3c9d490 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/mp3.c @@ -0,0 +1,189 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define MP3_DEBUG + +#ifdef MP3_DEBUG + +static short debug_level = 0; + +#define mp3_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mp3_printf(level, fmt, x...) +#endif + +#ifndef MP3_SILENT +#define mp3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mp3_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE + 22]; + mp3_printf(10, "\n"); + if (call == NULL) + { + mp3_err("call data is NULL...\n"); + return 0; + } + mp3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + mp3_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + mp3_err("file pointer < 0. ignoring ...\n"); + return 0; + } + call->private_size = 0; + uint32_t headerSize = InsertPesHeader(PesHeader, call->len + call->private_size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + if (call->private_size > 0) + { + memcpy(&PesHeader[headerSize], call->private_data, call->private_size); + headerSize += call->private_size; + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + int len = writev_with_retry(call->fd, iov, 2); + mp3_printf(10, "mp3_Write-< len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_mp3 = +{ + "mp3", + eAudio, + "A_MP3", + AUDIO_ENCODING_MP3, + AUDIOTYPE_MP3, + -1 +}; + +struct Writer_s WriterAudioMP3 = +{ + &reset, + &writeData, + NULL, + &caps_mp3 +}; + +static WriterCaps_t caps_mpegl3 = +{ + "mpeg/l3", + eAudio, + "A_MPEG/L3", + AUDIO_ENCODING_MPEG2, + AUDIOTYPE_MP3, + -1 +}; + +struct Writer_s WriterAudioMPEGL3 = +{ + &reset, + &writeData, + NULL, + &caps_mpegl3 +}; + +static WriterCaps_t caps_vorbis = +{ + "vorbis", + eAudio, + "A_VORBIS", + AUDIO_ENCODING_VORBIS, + AUDIO_ENCODING_MP3, + -1 +}; + +struct Writer_s WriterAudioVORBIS = +{ + &reset, + &writeData, + NULL, + &caps_vorbis +}; + diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg2.c b/libeplayer3-arm/output/writer/mipsel/mpeg2.c new file mode 100644 index 0000000..b15a4db --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/mpeg2.c @@ -0,0 +1,180 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define MPEG2_DEBUG + +#ifdef MPEG2_DEBUG + +static short debug_level = 0; + +#define mpeg2_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg2_printf(level, fmt, x...) +#endif + +#ifndef MPEG2_SILENT +#define mpeg2_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg2_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int len = 0; + unsigned int Position = 0; + mpeg2_printf(10, "\n"); + if (call == NULL) + { + mpeg2_err("call data is NULL...\n"); + return 0; + } + mpeg2_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + mpeg2_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + mpeg2_err("file pointer < 0. ignoring ...\n"); + return 0; + } + while (Position < call->len) + { + int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? + (call->len - Position) : MAX_PES_PACKET_SIZE; + int Remaining = call->len - Position - PacketLength; + mpeg2_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0); + iov[1].iov_base = call->data + Position; + iov[1].iov_len = PacketLength; + ssize_t l = writev_with_retry(call->fd, iov, 2); + if (l < 0) + { + len = l; + break; + } + len += l; + Position += PacketLength; + call->Pts = INVALID_PTS_VALUE; + } + mpeg2_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ +static WriterCaps_t caps = +{ + "mpeg2", + eVideo, + "V_MPEG2", + VIDEO_ENCODING_AUTO, + STREAMTYPE_MPEG2, + CT_MPEG2 +}; + +struct Writer_s WriterVideoMPEG2 = +{ + &reset, + &writeData, + NULL, + &caps +}; + +static WriterCaps_t mpg1_caps = +{ + "mpge1", + eVideo, + "V_MPEG1", + VIDEO_ENCODING_H264, + STREAMTYPE_MPEG1, + CT_MPEG1 +}; + +struct Writer_s WriterVideoMPEG1 = +{ + &reset, + &writeData, + NULL, + &mpg1_caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg4.c b/libeplayer3-arm/output/writer/mipsel/mpeg4.c new file mode 100644 index 0000000..f9f99b3 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/mpeg4.c @@ -0,0 +1,164 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define MPEG4_DEBUG +#else +#define MPEG4_SILENT +#endif + +#ifdef MPEG4_DEBUG + +static short debug_level = 0; + +#define mpeg4_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg4_printf(level, fmt, x...) +#endif + +#ifndef MPEG4_SILENT +#define mpeg4_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg4_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + mpeg4_printf(10, "\n"); + if (call == NULL) + { + mpeg4_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + mpeg4_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + mpeg4_err("file pointer < 0. ignoring ...\n"); + return 0; + } + mpeg4_printf(10, "VideoPts %lld\n", call->Pts); + unsigned int PacketLength = call->len; + if (initialHeader && call->private_size && call->private_data != NULL) + { + PacketLength += call->private_size; + } + struct iovec iov[3]; + int ic = 0; + iov[ic].iov_base = PesHeader; + iov[ic++].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + if (initialHeader && call->private_size && call->private_data != NULL) + { + initialHeader = 0; + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + } + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + int len = writev_with_retry(call->fd, iov, ic); + mpeg4_printf(10, "xvid_Write < len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t mpeg4p2_caps = +{ + "mpeg4p2", + eVideo, + "V_MPEG4", + VIDEO_ENCODING_MPEG4P2, + STREAMTYPE_MPEG4_Part2, + -1 +}; + +struct Writer_s WriterVideoMPEG4 = +{ + &reset, + &writeData, + NULL, + &mpeg4p2_caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/pcm.c b/libeplayer3-arm/output/writer/mipsel/pcm.c new file mode 100644 index 0000000..112c139 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/pcm.c @@ -0,0 +1,312 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" +#include "pcm.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define PCM_DEBUG +#else +#define PCM_SILENT +#endif + +#ifdef PCM_DEBUG + +static uint16_t debug_level = 0; + +#define pcm_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define pcm_printf(level, fmt, x...) +#endif + +#ifndef PCM_SILENT +#define pcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define pcm_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static uint8_t initialHeader = 1; +static uint8_t codec_data[18]; +static uint64_t fixed_buffertimestamp; +static uint64_t fixed_bufferduration; +static uint32_t fixed_buffersize; +static uint8_t *fixed_buffer; +static uint32_t fixed_bufferfilled; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + + +static int32_t reset() +{ + initialHeader = 1; + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + pcm_printf(10, "\n"); + if (!call) + { + pcm_err("call data is NULL...\n"); + return 0; + } + pcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) + { + pcm_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + pcm_err("file pointer < 0. ignoring ...\n"); + return 0; + } + static uint8_t PesHeader[PES_MAX_HEADER_SIZE + 22]; + pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; + uint8_t *buffer = call->data; + uint32_t size = call->len; + if (pcmPrivateData->bResampling || NULL == fixed_buffer) + { + if (0) + { + printf("ioctl %d", ioctl(call->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); + printf("ioctl %d", ioctl(call->fd, AUDIO_PAUSE)); + printf("ioctl %d", ioctl(call->fd, AUDIO_SET_BYPASS_MODE, 0x30)); + printf("ioctl %d", ioctl(call->fd, AUDIO_PLAY)); + printf("ioctl %d", ioctl(call->fd, AUDIO_CONTINUE)); + } + int32_t format = 0x01; + int32_t width = 0; + int32_t depth = 0; + int32_t rate = (uint64_t)pcmPrivateData->sample_rate; + int32_t channels = (uint8_t) pcmPrivateData->channels; + int32_t block_align = 0; + int32_t byterate = 0; + uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id; + uint8_t dataPrecision = 0; + uint8_t LE = 0; + switch (codecID) + { + case AV_CODEC_ID_PCM_S8: + case AV_CODEC_ID_PCM_U8: + width = depth = 8; + break; + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_U16LE: + LE = 1; + case AV_CODEC_ID_PCM_S16BE: + case AV_CODEC_ID_PCM_U16BE: + width = depth = 16; + break; + case AV_CODEC_ID_PCM_S24LE: + case AV_CODEC_ID_PCM_U24LE: + LE = 1; + case AV_CODEC_ID_PCM_S24BE: + case AV_CODEC_ID_PCM_U24BE: + width = depth = 24; + break; + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_U32LE: + LE = 1; + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_U32BE: + width = depth = 32; + break; + default: + break; + } + uint8_t *data = codec_data; + byterate = channels * rate * width / 8; + block_align = channels * width / 8; + memset(data, 0, sizeof(codec_data)); + /* format tag */ + *(data++) = format & 0xff; + *(data++) = (format >> 8) & 0xff; + /* channels */ + *(data++) = channels & 0xff; + *(data++) = (channels >> 8) & 0xff; + /* sample rate */ + *(data++) = rate & 0xff; + *(data++) = (rate >> 8) & 0xff; + *(data++) = (rate >> 16) & 0xff; + *(data++) = (rate >> 24) & 0xff; + /* byte rate */ + *(data++) = byterate & 0xff; + *(data++) = (byterate >> 8) & 0xff; + *(data++) = (byterate >> 16) & 0xff; + *(data++) = (byterate >> 24) & 0xff; + /* block align */ + *(data++) = block_align & 0xff; + *(data++) = (block_align >> 8) & 0xff; + /* word size */ + *(data++) = depth & 0xff; + *(data++) = (depth >> 8) & 0xff; + uint32_t nfixed_buffersize = rate * 30 / 1000; + nfixed_buffersize *= channels * depth / 8; + fixed_buffertimestamp = call->Pts; + fixed_bufferduration = 90000 * nfixed_buffersize / byterate; + if (fixed_buffersize != nfixed_buffersize || NULL == fixed_buffer) + { + fixed_buffersize = nfixed_buffersize; + if (NULL != fixed_buffer) + { + free(fixed_buffer); + } + fixed_buffer = malloc(fixed_buffersize); + } + fixed_bufferfilled = 0; + //printf("PCM fixed_buffersize [%u] [%s]\n", fixed_buffersize, LE ? "LE":"BE"); + } + while (size > 0) + { + uint32_t cpSize = (fixed_buffersize - fixed_bufferfilled); + if (cpSize > size) + { + memcpy(fixed_buffer + fixed_bufferfilled, buffer, size); + fixed_bufferfilled += size; + return size; + } + memcpy(fixed_buffer + fixed_bufferfilled, buffer, cpSize); + fixed_bufferfilled = 0; + buffer += cpSize; + size -= cpSize; + uint32_t addHeaderSize = 0; + if (IsDreambox()) + { + addHeaderSize = 4; + } + uint32_t headerSize = InsertPesHeader(PesHeader, fixed_buffersize + 4 + addHeaderSize + sizeof(codec_data), MPEG_AUDIO_PES_START_CODE, fixed_buffertimestamp, 0); + if (IsDreambox()) + { + PesHeader[headerSize++] = 0x42; // B + PesHeader[headerSize++] = 0x43; // C + PesHeader[headerSize++] = 0x4D; // M + PesHeader[headerSize++] = 0x41; // A + } + PesHeader[headerSize++] = (fixed_buffersize >> 24) & 0xff; + PesHeader[headerSize++] = (fixed_buffersize >> 16) & 0xff; + PesHeader[headerSize++] = (fixed_buffersize >> 8) & 0xff; + PesHeader[headerSize++] = fixed_buffersize & 0xff; + memcpy(PesHeader + headerSize, codec_data, sizeof(codec_data)); + headerSize += sizeof(codec_data); + PesHeader[6] |= 1; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize; + iov[1].iov_base = fixed_buffer; + iov[1].iov_len = fixed_buffersize; + writev_with_retry(call->fd, iov, 2); + fixed_buffertimestamp += fixed_bufferduration; + int g_fd_dump = open("/hdd/lpcm/ffmpeg.pes", O_CREAT | + O_RDWR | O_APPEND, S_IRUSR | S_IWUSR); + writev_with_retry(g_fd_dump, iov, 2); + close(g_fd_dump); + } + return size; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_pcm = +{ + "pcm", + eAudio, + "A_PCM", + AUDIO_ENCODING_LPCMA, + 0x30, + -1 +}; + +struct Writer_s WriterAudioPCM = +{ + &reset, + &writeData, + NULL, + &caps_pcm +}; + +static WriterCaps_t caps_ipcm = +{ + "ipcm", + eAudio, + "A_IPCM", + AUDIO_ENCODING_LPCMA, + 0x30, + -1 +}; + +struct Writer_s WriterAudioIPCM = +{ + &reset, + &writeData, /* writeDataIPCM */ + NULL, + &caps_ipcm +}; diff --git a/libeplayer3-arm/output/writer/mipsel/vc1.c b/libeplayer3-arm/output/writer/mipsel/vc1.c new file mode 100644 index 0000000..d8bc293 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/vc1.c @@ -0,0 +1,200 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80 +#define VC1_FRAME_START_CODE 0x0d + +#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define VC1_DEBUG +#else +#define VC1_SILENT +#endif + +#ifdef VC1_DEBUG + +static short debug_level = 10; + +#define vc1_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vc1_printf(level, fmt, x...) +#endif + +#ifndef VC1_SILENT +#define vc1_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vc1_err(fmt, x...) +#endif + + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +static const unsigned char SequenceLayerStartCode[] = {0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE}; +static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE}; + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; +static video_codec_data_t videocodecdata = {0, 0}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; + vc1_printf(10, "\n"); + if (call == NULL) + { + vc1_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + vc1_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + vc1_err("file pointer < 0. ignoring ...\n"); + return 0; + } + vc1_printf(10, "VideoPts %lld\n", call->Pts); + vc1_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)]; + int32_t ic = 0; + struct iovec iov[5]; + unsigned int PacketLength = 0; + iov[ic++].iov_base = PesHeader; + if (initialHeader) + { + initialHeader = 0; + if (videocodecdata.data) + { + free(videocodecdata.data); + videocodecdata.data = NULL; + } + videocodecdata.length = call->private_size + 8; + videocodecdata.data = malloc(videocodecdata.length); + memset(videocodecdata.data, 0, videocodecdata.length); + memcpy(videocodecdata.data + 8, call->private_data, call->private_size); + if (IsDreambox() || 0 != ioctl(call->fd, VIDEO_SET_CODEC_DATA, &videocodecdata)) + { + iov[ic].iov_base = videocodecdata.data; + iov[ic++].iov_len = videocodecdata.length; + PacketLength += videocodecdata.length; + } + } + uint8_t needFrameStartCode = 0; + if (sizeof(Vc1FrameStartCode) >= call->len + || memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0) + { + needFrameStartCode = 1; + PacketLength += sizeof(Vc1FrameStartCode); + } + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + /* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */ + PesHeader[6] |= 1; + if (needFrameStartCode) + { + memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); + iov[0].iov_len += sizeof(Vc1FrameStartCode); + } + if (videocodecdata.data) + { + free(videocodecdata.data); + videocodecdata.data = NULL; + } + return writev_with_retry(call->fd, iov, ic); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "vc1", + eVideo, + "V_VC1", + VIDEO_ENCODING_VC1, + STREAMTYPE_VC1, + CT_MPEG4_PART2 +}; + +struct Writer_s WriterVideoVC1 = +{ + &reset, + &writeData, + NULL, + &caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/vp.c b/libeplayer3-arm/output/writer/mipsel/vp.c new file mode 100644 index 0000000..eb9f98a --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/vp.c @@ -0,0 +1,228 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define VP_DEBUG +#else +#define VP_SILENT +#endif + +#ifdef VP_DEBUG + +static short debug_level = 10; + +#define vp_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vp_printf(level, fmt, x...) +#endif + +#ifndef VP_SILENT +#define vp_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vp_err(fmt, x...) +#endif + + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + return 0; +} + +static int writeData(void *_call, int is_vp6) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + vp_printf(10, "\n"); + if (call == NULL) + { + vp_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + vp_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + vp_err("file pointer < 0. ignoring ...\n"); + return 0; + } + vp_printf(10, "VideoPts %lld\n", call->Pts); + vp_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + uint32_t pes_header_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + uint32_t len = call->len + 4 + 6; + memcpy(PesHeader + pes_header_len, "BCMV", 4); + pes_header_len += 4; + if (is_vp6) + ++len; + PesHeader[pes_header_len++] = (len & 0xFF000000) >> 24; + PesHeader[pes_header_len++] = (len & 0x00FF0000) >> 16; + PesHeader[pes_header_len++] = (len & 0x0000FF00) >> 8; + PesHeader[pes_header_len++] = (len & 0x000000FF) >> 0; + PesHeader[pes_header_len++] = 0; + PesHeader[pes_header_len++] = 0; + if (is_vp6) + PesHeader[pes_header_len++] = 0; + iov[0].iov_len = pes_header_len; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev_with_retry(call->fd, iov, 2); +} + +static int writeDataVP6(void *_call) +{ + return writeData(_call, 1); +} + +static int writeDataVP89(void *_call) +{ + return writeData(_call, 0); +} + + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t capsVP6 = +{ + "vp6", + eVideo, + "V_VP6", + VIDEO_ENCODING_VC1, + STREAMTYPE_VB6, + CT_VP6 +}; + +struct Writer_s WriterVideoVP6 = +{ + &reset, + &writeDataVP6, + NULL, + &capsVP6 +}; + +static WriterCaps_t capsVP8 = +{ + "vp8", + eVideo, + "V_VP8", + VIDEO_ENCODING_VC1, + STREAMTYPE_VB8, + CT_VP8 +}; + +struct Writer_s WriterVideoVP8 = +{ + &reset, + &writeDataVP89, + NULL, + &capsVP8 +}; + +static WriterCaps_t capsVP9 = +{ + "vp9", + eVideo, + "V_VP9", + VIDEO_ENCODING_VC1, + STREAMTYPE_VB9, + CT_VP9 +}; + +struct Writer_s WriterVideoVP9 = +{ + &reset, + &writeDataVP89, + NULL, + &capsVP9 +}; + +static WriterCaps_t capsSPARK = +{ + "spark", + eVideo, + "V_SPARK", + VIDEO_ENCODING_VC1, + STREAMTYPE_SPARK, + CT_SPARK +}; + +struct Writer_s WriterVideoSPARK = +{ + &reset, + &writeDataVP89, + NULL, + &capsSPARK +}; diff --git a/libeplayer3-arm/output/writer/mipsel/wma.c b/libeplayer3-arm/output/writer/mipsel/wma.c new file mode 100644 index 0000000..83301a1 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/wma.c @@ -0,0 +1,202 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define WMA_DEBUG +#else +#define WMA_SILENT +#endif + +#ifdef WMA_DEBUG + +static short debug_level = 0; + +#define wma_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wma_printf(level, fmt, x...) +#endif + +#ifndef WMA_SILENT +#define wma_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wma_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static int initialHeader = 1; +static uint8_t *PesHeader = NULL; +static uint32_t MaxPesHeader = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; + wma_printf(10, "\n"); + if (call == NULL) + { + wma_err("call data is NULL...\n"); + return 0; + } + wma_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + wma_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + wma_err("file pointer < 0. ignoring ...\n"); + return 0; + } + uint32_t packetLength = 4 + call->private_size + call->len; + if (IsDreambox()) + { + packetLength += 4; + } + if ((packetLength + PES_MAX_HEADER_SIZE) > MaxPesHeader) + { + if (PesHeader) + { + free(PesHeader); + } + MaxPesHeader = packetLength + PES_MAX_HEADER_SIZE; + PesHeader = malloc(MaxPesHeader); + } + uint32_t headerSize = InsertPesHeader(PesHeader, packetLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + if (IsDreambox()) + { + PesHeader[headerSize++] = 0x42; // B + PesHeader[headerSize++] = 0x43; // C + PesHeader[headerSize++] = 0x4D; // M + PesHeader[headerSize++] = 0x41; // A + } + size_t payload_len = call->len; + PesHeader[headerSize++] = (payload_len >> 24) & 0xff; + PesHeader[headerSize++] = (payload_len >> 16) & 0xff; + PesHeader[headerSize++] = (payload_len >> 8) & 0xff; + PesHeader[headerSize++] = payload_len & 0xff; + memcpy(PesHeader + headerSize, call->private_data, call->private_size); + headerSize += call->private_size; + PesHeader[6] |= 1; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev_with_retry(call->fd, iov, 2); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t capsWMAPRO = +{ + "wma/pro", + eAudio, + "A_WMA/PRO", + AUDIO_ENCODING_WMA, + AUDIOTYPE_WMA_PRO, + -1 +}; + +struct Writer_s WriterAudioWMAPRO = +{ + &reset, + &writeData, + NULL, + &capsWMAPRO +}; + + +static WriterCaps_t capsWMA = +{ + "wma", + eAudio, + "A_WMA", + AUDIO_ENCODING_WMA, + AUDIOTYPE_WMA, + -1 +}; + +struct Writer_s WriterAudioWMA = +{ + &reset, + &writeData, + NULL, + &capsWMA +}; diff --git a/libeplayer3-arm/output/writer/mipsel/wmv.c b/libeplayer3-arm/output/writer/mipsel/wmv.c new file mode 100644 index 0000000..e9b7053 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/wmv.c @@ -0,0 +1,206 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm_ioctls.h" +#include "bcm_ioctls.h" + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define WMV_FRAME_START_CODE 0x0d + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define WMV_DEBUG +#else +#define WMV_SILENT +#endif + +#ifdef WMV_DEBUG + +static short debug_level = 10; + +#define wmv_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wmv_printf(level, fmt, x...) +#endif + +#ifndef WMV_SILENT +#define wmv_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wmv_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, WMV_FRAME_START_CODE}; + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; +static video_codec_data_t videocodecdata = {0, 0}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + wmv_printf(10, "\n"); + if (call == NULL) + { + wmv_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + wmv_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + wmv_err("file pointer < 0. ignoring ...\n"); + return 0; + } + wmv_printf(10, "VideoPts %lld\n", call->Pts); + wmv_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)]; + int32_t ic = 0; + struct iovec iov[5]; + unsigned int PacketLength = 0; + iov[ic++].iov_base = PesHeader; + if (initialHeader) + { + initialHeader = 0; + if (videocodecdata.data) + { + free(videocodecdata.data); + videocodecdata.data = NULL; + } + unsigned int codec_size = call->private_size; + if (codec_size > 4) codec_size = 4; + videocodecdata.length = 33; + uint8_t *data = videocodecdata.data = malloc(videocodecdata.length); + memset(videocodecdata.data, 0, videocodecdata.length); + data += 18; + /* width */ + *(data++) = (call->Width >> 8) & 0xff; + *(data++) = call->Width & 0xff; + /* height */ + *(data++) = (call->Height >> 8) & 0xff; + *(data++) = call->Height & 0xff; + if (call->private_data && codec_size) memcpy(data, call->private_data, codec_size); + if (IsDreambox() || 0 != ioctl(call->fd, VIDEO_SET_CODEC_DATA, &videocodecdata)) + { + iov[ic].iov_base = videocodecdata.data; + iov[ic++].iov_len = videocodecdata.length; + PacketLength += videocodecdata.length; + } + } + uint8_t needFrameStartCode = 0; + if (sizeof(Vc1FrameStartCode) >= call->len + || memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0) + { + needFrameStartCode = 1; + PacketLength += sizeof(Vc1FrameStartCode); + } + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + /* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */ + PesHeader[6] |= 1; + if (needFrameStartCode) + { + memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); + iov[0].iov_len += sizeof(Vc1FrameStartCode); + } + if (videocodecdata.data) + { + free(videocodecdata.data); + videocodecdata.data = NULL; + } + return writev_with_retry(call->fd, iov, ic); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "wmv", + eVideo, + "V_WMV", + VIDEO_ENCODING_WMV, + STREAMTYPE_VC1_SM, + CT_MPEG4_PART2 +}; + +struct Writer_s WriterVideoWMV = +{ + &reset, + &writeData, + NULL, + &caps +}; diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c new file mode 100644 index 0000000..bc63bb0 --- /dev/null +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -0,0 +1,204 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ +#include +#include +#include + +#include "misc.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define WRITER_DEBUG + +#ifdef WRITER_DEBUG + +static short debug_level = 0; + +#define writer_printf(level, x...) do { \ + if (debug_level >= level) printf(x); } while (0) +#else +#define writer_printf(level, x...) +#endif + +#ifndef WRITER_SILENT +#define writer_err(x...) do { printf(x); } while (0) +#else +#define writer_err(x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Writer_t *AvailableWriter[] = +{ + &WriterAudioAAC, + &WriterAudioAACLATM, + &WriterAudioAACLATM, + &WriterAudioAACPLUS, + &WriterAudioAC3, + &WriterAudioEAC3, + &WriterAudioMP3, + &WriterAudioMPEGL3, + &WriterAudioPCM, + &WriterAudioIPCM, + &WriterAudioLPCM, + &WriterAudioDTS, + &WriterAudioWMA, + &WriterAudioWMAPRO, + + &WriterVideoH264, + &WriterVideoH265, + &WriterVideoH263, + &WriterVideoMPEG4, + &WriterVideoMPEG2, + &WriterVideoMPEG1, + &WriterVideoVC1, + &WriterVideoDIVX3, + &WriterVideoVP6, + &WriterVideoVP8, + &WriterVideoVP9, + &WriterVideoSPARK, + &WriterVideoWMV, + NULL +}; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ +ssize_t write_with_retry(int fd, const void *buf, size_t size) +{ + ssize_t ret; + int retval = 0; + while (size > 0 && 0 == PlaybackDieNow(0)) + { + ret = write(fd, buf, size); + //printf("[%d] write [%lld]\n", fd, ret); + if (ret < 0) + { + switch (errno) + { + case EINTR: + case EAGAIN: + usleep(1000); + continue; + default: + retval = -3; + break; + } + if (retval < 0) + { + break; + } + } + if (ret < 0) + { + return ret; + } + size -= ret; + buf += ret; + if (size > 0) + { + if (usleep(1000)) + { + writer_err("usleep error \n"); + } + } + } + return 0; +} + +ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic) +{ + ssize_t len = 0; + int i = 0; + for (i = 0; i < ic; ++i) + { + write_with_retry(fd, iov[i].iov_base, iov[i].iov_len); + len += iov[i].iov_len; + if (PlaybackDieNow(0)) + { + return -1; + } + } + return len; +} + +Writer_t *getWriter(char *encoding) +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0) + { + writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, encoding); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding); + return NULL; +} + +Writer_t *getDefaultVideoWriter() +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0) + { + writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; +} + +Writer_t *getDefaultAudioWriter() +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0) + { + writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; +} + diff --git a/libeplayer3-arm/output/writer/sh4/aac.c b/libeplayer3-arm/output/writer/sh4/aac.c new file mode 100644 index 0000000..0dd2e9f --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/aac.c @@ -0,0 +1,372 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "ffmpeg/latmenc.h" + + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" +#include "aac.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +//#define SAM_WITH_DEBUG + +#ifdef SAM_WITH_DEBUG +#define AAC_DEBUG +#else +#define AAC_SILENT +#endif + +#ifdef AAC_DEBUG + +static short debug_level = 0; + +#define aac_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define aac_printf(level, fmt, x...) +#endif + +#ifndef AAC_SILENT +#define aac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define aac_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/// ** AAC ADTS format ** +/// +/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM +/// MMMMMMMM MMMNNNNN NNNNNNOO ........ +/// +/// Sign Length Position Description +/// +/// A 12 (31-20) Sync code +/// B 1 (19) ID +/// C 2 (18-17) layer +/// D 1 (16) protect absent +/// E 2 (15-14) profile +/// F 4 (13-10) sample freq index +/// G 1 (9) private +/// H 3 (8-6) channel config +/// I 1 (5) original/copy +/// J 1 (4) home +/// K 1 (3) copyright id +/// L 1 (2) copyright start +/// M 13 (1-0,31-21) frame length +/// N 11 (20-10) adts buffer fullness +/// O 2 (9-8) num of raw data blocks in frame + +/* +LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc +HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc +*/ + +/* +ADIF = basic format called Audio Data Interchange Format (ADIF) + consisting of a single header followed by the raw AAC audio data blocks +ADTS = streaming format called Audio Data Transport Stream (ADTS) + consisting of a series of frames, each frame having a header followed by the AAC audio data +LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format +*/ + +static unsigned char DefaultAACHeader[] = +{ + 0xff, + 0xf1, + /*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s + 0x80, //(Channels & 0x03) << 6; + 0x00, + 0x1f, + 0xfc +}; + +LATMContext *pLATMCtx = NULL; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + if (pLATMCtx) + { + free(pLATMCtx); + pLATMCtx = NULL; + } + return 0; +} + +static int _writeData(void *_call, int type) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n _writeData type[%d]\n", type); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len < 8)) + { + aac_err("parsing Data with missing AAC header. ignoring...\n"); + return 0; + } + /* simple validation */ + if (0 == type) // check ADTS header + { + if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1])) + { + aac_err("parsing Data with missing syncword. ignoring...\n"); + return 0; + } + } + else // check LOAS header + { + if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe && + (AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len)) + { + aac_err("parsing Data with wrong latm header. ignoring...\n"); + return 0; + } + } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev(call->fd, iov, 2); +} + +static int writeDataADTS(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + aac_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + aac_err("file pointer < 0. ignoring ...\n"); + return 0; + } + if ((call->private_data && 0 == strncmp("ADTS", call->private_data, call->private_size)) || + HasADTSHeader(call->data, call->len)) + { + return _writeData(_call, 0); + } + uint32_t PacketLength = call->len + AAC_HEADER_LENGTH; + uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH]; + uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + uint8_t *pExtraData = &PesHeader[headerSize]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (call->private_data == NULL) + { + aac_printf(10, "private_data = NULL\n"); + memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH); + } + else + { + memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH); + } + pExtraData[3] &= 0xC0; + /* frame size over last 2 bits */ + pExtraData[3] |= (PacketLength & 0x1800) >> 11; + /* frame size continued over full byte */ + pExtraData[4] = (PacketLength & 0x1FF8) >> 3; + /* frame size continued first 3 bits */ + pExtraData[5] = (PacketLength & 7) << 5; + /* buffer fullness(0x7FF for VBR) over 5 last bits */ + pExtraData[5] |= 0x1F; + /* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for + * number of raw data blocks */ + pExtraData[6] = 0xFC; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = headerSize + AAC_HEADER_LENGTH; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev(call->fd, iov, 2); +} + +static int writeDataLATM(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) + { + aac_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + aac_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->private_data && 0 == strncmp("LATM", call->private_data, call->private_size)) + { + return _writeData(_call, 1); + } + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (!pLATMCtx) + { + pLATMCtx = malloc(sizeof(LATMContext)); + memset(pLATMCtx, 0x00, sizeof(LATMContext)); + pLATMCtx->mod = 14; + pLATMCtx->counter = 0; + } + if (!pLATMCtx) + { + aac_err("parsing NULL pLATMCtx. ignoring...\n"); + return 0; + } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); + if (ret) + { + printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ + (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + aac_err("latm_decode_extradata failed. ignoring...\n"); + return 0; + } + ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size); + if (ret) + { + aac_err("latm_write_packet failed. ignoring...\n"); + return 0; + } + unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[3]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = pLATMCtx->loas_header; + iov[1].iov_len = 3; + iov[2].iov_base = pLATMCtx->buffer; + iov[2].iov_len = pLATMCtx->len; + return writev(call->fd, iov, 3); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "aac", + eAudio, + "A_AAC", + AUDIO_ENCODING_AAC, + -1, + -1 +}; + +struct Writer_s WriterAudioAAC = +{ + &reset, + &writeDataADTS, + NULL, + &caps +}; + +static WriterCaps_t caps_aac_latm = +{ + "aac", + eAudio, + "A_AAC_LATM", + AUDIO_ENCODING_AAC, + -1, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM + -1 +}; + +struct Writer_s WriterAudioAACLATM = +{ + &reset, + &writeDataLATM, + NULL, + &caps_aac_latm +}; + +static WriterCaps_t caps_aacplus = +{ + "aac", + eAudio, + "A_AAC_PLUS", + AUDIO_ENCODING_AAC, + -1, + -1 +}; + +struct Writer_s WriterAudioAACPLUS = +{ + &reset, + &writeDataADTS, + NULL, + &caps_aacplus +}; \ No newline at end of file diff --git a/libeplayer3-arm/output/writer/sh4/ac3.c b/libeplayer3-arm/output/writer/sh4/ac3.c new file mode 100644 index 0000000..de2f44b --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/ac3.c @@ -0,0 +1,165 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define AC3_HEADER_LENGTH 7 + +#ifdef SAM_WITH_DEBUG +#define AC3_DEBUG +#else +#define AC3_SILENT +#endif + +#ifdef AC3_DEBUG + +static short debug_level = 0; + +#define ac3_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ac3_printf(level, fmt, x...) +#endif + +#ifndef AC3_SILENT +#define ac3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define ac3_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + ac3_printf(10, "\n"); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if (call == NULL) + { + ac3_err("call data is NULL...\n"); + return 0; + } + ac3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + ac3_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + ac3_err("file pointer < 0. ignoring ...\n"); + return 0; + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len, PRIVATE_STREAM_1_PES_START_CODE, call->Pts, 0); + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + return writev(call->fd, iov, 2); +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_ac3 = +{ + "ac3", + eAudio, + "A_AC3", + AUDIO_ENCODING_AC3, + -1, + -1 +}; + +struct Writer_s WriterAudioAC3 = +{ + &reset, + &writeData, + NULL, + &caps_ac3 +}; + +static WriterCaps_t caps_eac3 = +{ + "ac3", + eAudio, + "A_EAC3", + AUDIO_ENCODING_AC3, + -1, + -1 +}; + +struct Writer_s WriterAudioEAC3 = +{ + &reset, + &writeData, + NULL, + &caps_eac3 +}; \ No newline at end of file diff --git a/libeplayer3-arm/output/writer/sh4/divx.c b/libeplayer3-arm/output/writer/sh4/divx.c new file mode 100644 index 0000000..4f4cdc9 --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/divx.c @@ -0,0 +1,237 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define DIVX_DEBUG +#else +#define DIVX_SILENT +#endif + +#ifdef DIVX_DEBUG + +static short debug_level = 0; + +#define divx_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_printf(level, fmt, x...) +#endif + +#ifndef DIVX_SILENT +#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static uint8_t updateCodecData(uint8_t *data, int32_t size) +{ + static uint8_t *oldData = NULL; + static int32_t oldSize = 0; + uint8_t update = 0; + if (data != NULL && size > 0) + { + if (size != oldSize) + { + update = 1; + } + else + { + uint32_t i = 0; + for (i = 0; i < size; i++) + { + if (data[i] != oldData[i]) + { + update = 1; + break; + } + } + } + } + if (update) + { + if (oldData != NULL) + { + free(oldData); + } + oldData = malloc(size); + memcpy(oldData, data, size); + oldSize = size; + } + return update; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + divx_printf(10, "\n"); + if (call == NULL) + { + divx_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + divx_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + divx_err("file pointer < 0. ignoring ...\n"); + return 0; + } + divx_printf(10, "VideoPts %lld\n", call->Pts); + struct iovec iov[4]; + int ic = 0; + iov[ic].iov_base = PesHeader; + iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + if (updateCodecData(call->private_data, call->private_size)) + { + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + } + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + int len = writev(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t mpeg4p2_caps = +{ + "mpeg4p2", + eVideo, + "V_MPEG4", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoMPEG4 = +{ + &reset, + &writeData, + NULL, + &mpeg4p2_caps +}; + + +struct Writer_s WriterVideoMSCOMP = +{ + &reset, + &writeData, + NULL, + &mpeg4p2_caps +}; + +static WriterCaps_t fourcc_caps = +{ + "fourcc", + eVideo, + "V_MS/VFW/FOURCC", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoFOURCC = +{ + &reset, + &writeData, + NULL, + &fourcc_caps +}; + +static WriterCaps_t divx_caps = +{ + "divx", + eVideo, + "V_MKV/XVID", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoDIVX = +{ + &reset, + &writeData, + NULL, + &divx_caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/divx2.c b/libeplayer3-arm/output/writer/sh4/divx2.c new file mode 100644 index 0000000..99bfcc7 --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/divx2.c @@ -0,0 +1,263 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define DIVX_DEBUG +#else +#define DIVX_SILENT +#endif + +#ifdef DIVX_DEBUG + +static short debug_level = 0; + +#define divx_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_printf(level, fmt, x...) +#endif + +#ifndef DIVX_SILENT +#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define divx_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static uint8_t updateCodecData(uint8_t *data, int32_t size) +{ + static uint8_t *oldData = NULL; + static int32_t oldSize = 0; + uint8_t update = 0; + if (data != NULL && size > 0) + { + if (size != oldSize) + { + update = 1; + } + else + { + uint32_t i = 0; + for (i = 0; i < size; i++) + { + if (data[i] != oldData[i]) + { + update = 1; + break; + } + } + } + } + if (update) + { + if (oldData != NULL) + { + free(oldData); + } + oldData = malloc(size); + memcpy(oldData, data, size); + oldSize = size; + } + return update; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + unsigned char FakeHeaders[64]; // 64bytes should be enough to make the fake headers + unsigned int FakeHeaderLength; + unsigned char Version = 5; + unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE; + unsigned int usecPerFrame = 41708; /* Hellmaster1024: default value */ + BitPacker_t ld = {FakeHeaders, 0, 32}; + divx_printf(10, "\n"); + if (call == NULL) + { + divx_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + divx_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + divx_err("file pointer < 0. ignoring ...\n"); + return 0; + } + divx_printf(10, "AudioPts %lld\n", call->Pts); + usecPerFrame = 1000000000 / call->FrameRate; + divx_printf(10, "Microsecends per frame = %d\n", usecPerFrame); + memset(FakeHeaders, 0, sizeof(FakeHeaders)); + /* Create info record for frame parser */ + /* divx4 & 5 + VOS + PutBits(&ld, 0x0, 8); + PutBits(&ld, 0x0, 8); + */ + PutBits(&ld, 0x1b0, 32); // startcode + PutBits(&ld, 0, 8); // profile = reserved + PutBits(&ld, 0x1b2, 32); // startcode (user data) + PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file + PutBits(&ld, usecPerFrame, 32); + // microseconds per frame + FlushBits(&ld); + FakeHeaderLength = (ld.Ptr - (FakeHeaders)); + struct iovec iov[4]; + int ic = 0; + iov[ic].iov_base = PesHeader; + iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode); + iov[ic].iov_base = FakeHeaders; + iov[ic++].iov_len = FakeHeaderLength; + if (initialHeader) + { + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + initialHeader = 0; + } + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + int len = writev(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t mpeg4p2_caps = +{ + "mpeg4p2", + eVideo, + "V_MPEG4", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoMPEG4 = +{ + &reset, + &writeData, + NULL, + &mpeg4p2_caps +}; + + +struct Writer_s WriterVideoMSCOMP = +{ + &reset, + &writeData, + NULL, + &mpeg4p2_caps +}; + +static WriterCaps_t fourcc_caps = +{ + "fourcc", + eVideo, + "V_MS/VFW/FOURCC", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoFOURCC = +{ + &reset, + &writeData, + NULL, + &fourcc_caps +}; + +static WriterCaps_t divx_caps = +{ + "divx", + eVideo, + "V_MKV/XVID", + VIDEO_ENCODING_MPEG4P2, + -1, + -1 +}; + +struct Writer_s WriterVideoDIVX = +{ + &reset, + &writeData, + NULL, + &divx_caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/dts.c b/libeplayer3-arm/output/writer/sh4/dts.c new file mode 100644 index 0000000..514bd7a --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/dts.c @@ -0,0 +1,176 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size. +#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE) +#define PES_AUDIO_PACKET_SIZE 2028 +#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples. + +#ifdef SAM_WITH_DEBUG +#define DTS_DEBUG +#else +#define DTS_SILENT +#endif + +#ifdef DTS_DEBUG + +static short debug_level = 0; + +#define dts_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define dts_printf(level, fmt, x...) +#endif + +#ifndef DTS_SILENT +#define dts_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define dts_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_AUDIO_HEADER_SIZE]; + dts_printf(10, "\n"); + if (call == NULL) + { + dts_err("call data is NULL...\n"); + return 0; + } + dts_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + dts_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + dts_err("file pointer < 0. ignoring ...\n"); + return 0; + } + uint8_t *Data = call->data; + int32_t Size = call->len; +#ifdef CHECK_FOR_DTS_HD + int32_t pos = 0; + while ((pos + 4) <= Size) + { + // check for DTS-HD + if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25")) + { + Size = pos; + break; + } + ++pos; + } +#endif +// #define DO_BYTESWAP +#ifdef DO_BYTESWAP + /* 16-bit byte swap all data before injecting it */ + for (i = 0; i < Size; i += 2) + { + uint8_t Tmp = Data[i]; + Data[i] = Data[i + 1]; + Data[i + 1] = Tmp; + } +#endif + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + iov[1].iov_base = Data; + iov[1].iov_len = Size; + int32_t len = writev(call->fd, iov, 2); + dts_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "dts", + eAudio, + "A_DTS", + AUDIO_ENCODING_DTS, + -1, + -1 +}; + +struct Writer_s WriterAudioDTS = +{ + &reset, + &writeData, + NULL, + &caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/h263.c b/libeplayer3-arm/output/writer/sh4/h263.c new file mode 100644 index 0000000..4f86fa9 --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/h263.c @@ -0,0 +1,173 @@ +/* + * linuxdvb output/writer handling. + * + * crow 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define H263_DEBUG +#else +#define H263_SILENT +#endif + +#ifdef H263_DEBUG +static short debug_level = 0; +static const char *FILENAME = "h263.c"; + +#define h263_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) +#else +#define h263_printf(level, fmt, x...) +#endif + +#ifndef H263_SILENT +#define h263_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0) +#else +#define h263_err(fmt, x...) +#endif +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int len = 0; + h263_printf(10, "\n"); + if (call == NULL) + { + h263_err("call data is NULL...\n"); + return 0; + } + h263_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + h263_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h263_err("file pointer < 0. ignoring ...\n"); + return 0; + } + int HeaderLength = InsertPesHeader(PesHeader, call->len, H263_VIDEO_PES_START_CODE, call->Pts, 0); + int PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len); + int PesLength = PesHeader[PES_LENGTH_BYTE_0] + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength; + PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff; + PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; + PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; + PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; + HeaderLength += PrivateHeaderLength; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + len = writev(call->fd, iov, 2); + h263_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_h263 = +{ + "h263", + eVideo, + "V_H263", + VIDEO_ENCODING_H263, + -1, + -1 +}; + +struct Writer_s WriterVideoH263 = +{ + &reset, + &writeData, + NULL, + &caps_h263 +}; + +static WriterCaps_t caps_flv = +{ + "FLV", + eVideo, + "V_FLV", + VIDEO_ENCODING_FLV1, + -1, + -1 +}; + +struct Writer_s WriterVideoFLV = +{ + &reset, + &writeData, + NULL, + &caps_flv +}; diff --git a/libeplayer3-arm/output/writer/sh4/h264.c b/libeplayer3-arm/output/writer/sh4/h264.c new file mode 100644 index 0000000..eee45dd --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/h264.c @@ -0,0 +1,480 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define H264_DEBUG +#else +#define H264_SILENT +#endif + +#ifdef H264_DEBUG + +static short debug_level = 0; + +#define h264_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_printf(level, fmt, x...) +#endif + +#ifndef H264_SILENT +#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define h264_err(fmt, x...) +#endif + +#define NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS 24 +#define CONTAINER_PARAMETERS_VERSION 0x00 + +/* ***************************** */ +/* Types */ +/* ***************************** */ +typedef struct avcC_s +{ + unsigned char Version; /* configurationVersion */ + unsigned char Profile; /* AVCProfileIndication */ + unsigned char Compatibility; /* profile_compatibility */ + unsigned char Level; /* AVCLevelIndication */ + unsigned char NalLengthMinusOne; /* held in bottom two bits */ + unsigned char NumParamSets; /* held in bottom 5 bits */ + unsigned char Params[1]; /* {length,params}{length,params}...sequence then picture*/ +} avcC_t; + + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +const uint8_t Head[] = {0, 0, 0, 1}; +static int32_t initialHeader = 1; +static uint32_t NalLengthBytes = 1; +static int avc3 = 0; +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771 +static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize) +{ + uint8_t *aExtraData = *ppExtraData; + if (aExtraData[0] != 1 || !pData) + { + // Not AVCC or nothing to update with. + return -1; + } + int32_t nalsize = (aExtraData[4] & 3) + 1; + uint8_t sps[256]; + uint8_t spsIdx = 0; + uint8_t numSps = 0; + uint8_t pps[256]; + uint8_t ppsIdx = 0; + uint8_t numPps = 0; + if (nalsize != 4) + { + return -1; + } + // Find SPS and PPS NALUs in AVCC data + uint8_t *d = pData; + while (d + 4 < pData + dataSize) + { + uint32_t nalLen = ReadUint32(d); + uint8_t nalType = d[4] & 0x1f; + if (nalType == 7) + { + /* SPS */ + // 16 bits size + sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); + sps[spsIdx++] = (uint8_t)(0xFF & nalLen); + if (spsIdx + nalLen >= sizeof(sps)) + { + h264_err("SPS no free space to copy...\n"); + return -1; + } + memcpy(&(sps[spsIdx]), d + 4, nalLen); + spsIdx += nalLen; + numSps += 1; + h264_printf(10, "SPS len[%u]...\n", nalLen); + } + else if (nalType == 8) + { + /* PPS */ + // 16 bits size + pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); + pps[ppsIdx++] = (uint8_t)(0xFF & nalLen); + if (ppsIdx + nalLen >= sizeof(sps)) + { + h264_err("PPS not free space to copy...\n"); + return -1; + } + memcpy(&(pps[ppsIdx]), d + 4, nalLen); + ppsIdx += nalLen; + numPps += 1; + h264_printf(10, "PPS len[%u]...\n", nalLen); + } + d += 4 + nalLen; + } + uint32_t idx = 0; + *ppExtraData = malloc(7 + spsIdx + ppsIdx); + aExtraData = *ppExtraData; + aExtraData[idx++] = 0x1; // version + aExtraData[idx++] = sps[3]; // profile + aExtraData[idx++] = sps[4]; // profile compat + aExtraData[idx++] = sps[5]; // level + aExtraData[idx++] = 0xff; // nal size - 1 + aExtraData[idx++] = 0xe0 | numSps; + if (numSps) + { + memcpy(&(aExtraData[idx]), sps, spsIdx); + idx += spsIdx; + } + aExtraData[idx++] = numPps; + if (numPps) + { + memcpy(&(aExtraData[idx]), pps, ppsIdx); + idx += ppsIdx; + } + h264_printf(10, "aExtraData len[%u]...\n", idx); + *pExtraDataSize = idx; + return 0; +} + +static int32_t reset() +{ + initialHeader = 1; + avc3 = 0; + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_MAX_HEADER_SIZE]; + uint64_t VideoPts; + uint32_t TimeDelta; + uint32_t TimeScale; + int32_t len = 0; + int32_t ic = 0; + struct iovec iov[128]; + h264_printf(10, "\n"); + if (call == NULL) + { + h264_err("call data is NULL...\n"); + return 0; + } + TimeDelta = call->FrameRate; + TimeScale = call->FrameScale; + VideoPts = call->Pts; + h264_printf(10, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) + { + h264_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h264_err("file pointer < 0. ignoring ...\n"); + return 0; + } + /* AnnexA */ + if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) || + (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || + (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)))) + { + uint32_t PacketLength = 0; + uint32_t FakeStartCode = /*(call->Version << 8) | */PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; + initialHeader = 0; + if (initialHeader) + { + initialHeader = 0; + iov[ic].iov_base = call->private_data; + iov[ic++].iov_len = call->private_size; + PacketLength += call->private_size; + } + iov[ic].iov_base = ""; + iov[ic++].iov_len = 1; + iov[ic].iov_base = call->data; + iov[ic++].iov_len = call->len; + PacketLength += call->len; + /*Hellmaster1024: some packets will only be accepted by the player if we send one byte more than + data is available. The content of this byte does not matter. It will be ignored + by the player */ + iov[ic].iov_base = "\0"; + iov[ic++].iov_len = 1; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); + int ret = writev(call->fd, iov, ic); + return ret; + } + else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0]) + { + h264_err("No valid private data available!\n"); + return 0; + } + if (initialHeader) + { + uint8_t *private_data = call->private_data; + uint32_t private_size = call->private_size; + avcC_t *avcCHeader = (avcC_t *)private_data; + unsigned int i; + unsigned int ParamSets; + unsigned int ParamOffset; + unsigned int InitialHeaderLength = 0; + unsigned int ParametersLength; + ParametersLength = 0; + unsigned char HeaderData[19]; + if (private_size <= sizeof(avcC_t)) + { + UpdateExtraData(&private_data, &private_size, call->data, call->len); + if (private_data != call->private_data) + { + avc3 = 1; + avcCHeader = (avcC_t *)private_data; + } + } + HeaderData[ParametersLength++] = 0x00; // Start code + HeaderData[ParametersLength++] = 0x00; + HeaderData[ParametersLength++] = 0x01; + HeaderData[ParametersLength++] = NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS; + // Container message version - changes when/if we vary the format of the message + HeaderData[ParametersLength++] = CONTAINER_PARAMETERS_VERSION; + HeaderData[ParametersLength++] = 0xff; // Field separator + if (TimeDelta == 0xffffffff) + TimeDelta = (TimeScale > 1000) ? 1001 : 1; + HeaderData[ParametersLength++] = (TimeScale >> 24) & 0xff; // Output the timescale + HeaderData[ParametersLength++] = (TimeScale >> 16) & 0xff; + HeaderData[ParametersLength++] = 0xff; + HeaderData[ParametersLength++] = (TimeScale >> 8) & 0xff; + HeaderData[ParametersLength++] = TimeScale & 0xff; + HeaderData[ParametersLength++] = 0xff; + HeaderData[ParametersLength++] = (TimeDelta >> 24) & 0xff; // Output frame period + HeaderData[ParametersLength++] = (TimeDelta >> 16) & 0xff; + HeaderData[ParametersLength++] = 0xff; + HeaderData[ParametersLength++] = (TimeDelta >> 8) & 0xff; + HeaderData[ParametersLength++] = TimeDelta & 0xff; + HeaderData[ParametersLength++] = 0xff; + HeaderData[ParametersLength++] = 0x80; // Rsbp trailing bits + assert(ParametersLength <= sizeof(HeaderData)); + ic = 0; + iov[ic].iov_base = PesHeader; + iov[ic++].iov_len = InsertPesHeader(PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + iov[ic].iov_base = HeaderData; + iov[ic++].iov_len = ParametersLength; + len = writev(call->fd, iov, ic); + if (len < 0) + { + return len; + } + NalLengthBytes = (avcCHeader->NalLengthMinusOne & 0x03) + 1; + ParamSets = avcCHeader->NumParamSets & 0x1f; + h264_printf(20, "avcC contents:\n"); + h264_printf(20, " version: %d\n", avcCHeader->Version); + h264_printf(20, " profile: %d\n", avcCHeader->Profile); + h264_printf(20, " profile compatibility: %d\n", avcCHeader->Compatibility); + h264_printf(20, " level: %d\n", avcCHeader->Level); + h264_printf(20, " nal length bytes: %d\n", NalLengthBytes); + h264_printf(20, " number of sequence param sets: %d\n", ParamSets); + ParamOffset = 0; + ic = 0; + iov[ic++].iov_base = PesHeader; + for (i = 0; i < ParamSets; i++) + { + unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1]; + h264_printf(20, " sps %d has length %d\n", i, PsLength); + iov[ic].iov_base = (char *)Head; + iov[ic++].iov_len = sizeof(Head); + InitialHeaderLength += sizeof(Head); + iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2]; + iov[ic++].iov_len = PsLength; + InitialHeaderLength += PsLength; + ParamOffset += PsLength + 2; + } + ParamSets = avcCHeader->Params[ParamOffset]; + h264_printf(20, " number of picture param sets: %d\n", ParamSets); + ParamOffset++; + for (i = 0; i < ParamSets; i++) + { + unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1]; + h264_printf(20, " pps %d has length %d\n", i, PsLength); + iov[ic].iov_base = (char *) Head; + iov[ic++].iov_len = sizeof(Head); + InitialHeaderLength += sizeof(Head); + iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2]; + iov[ic++].iov_len = PsLength; + InitialHeaderLength += PsLength; + ParamOffset += PsLength + 2; + } + iov[0].iov_len = InsertPesHeader(PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + ssize_t l = writev(call->fd, iov, ic); + if (private_data != call->private_data) + { + free(private_data); + } + if (l < 0) + { + return l; + } + len += l; + initialHeader = 0; + } + unsigned int SampleSize = call->len; + unsigned int NalStart = 0; + unsigned int VideoPosition = 0; + do + { + unsigned int NalLength; + unsigned char NalData[4]; + int NalPresent = 1; + memcpy(NalData, call->data + VideoPosition, NalLengthBytes); + VideoPosition += NalLengthBytes; + NalStart += NalLengthBytes; + switch (NalLengthBytes) + { + case 1: + NalLength = (NalData[0]); + break; + case 2: + NalLength = (NalData[0] << 8) | (NalData[1]); + break; + case 3: + NalLength = (NalData[0] << 16) | (NalData[1] << 8) | (NalData[2]); + break; + default: + NalLength = (NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8) | (NalData[3]); + break; + } + h264_printf(20, "NalStart = %u + NalLength = %u > SampleSize = %u\n", NalStart, NalLength, SampleSize); + if (NalStart + NalLength > SampleSize) + { + h264_printf(20, "nal length past end of buffer - size %u frame offset %u left %u\n", + NalLength, NalStart, SampleSize - NalStart); + NalStart = SampleSize; + } + else + { + NalStart += NalLength; + ic = 0; + iov[ic++].iov_base = PesHeader; + if (NalPresent) + { + NalPresent = 0; + iov[ic].iov_base = (char *)Head; + iov[ic++].iov_len = sizeof(Head); + } + iov[ic].iov_base = call->data + VideoPosition; + iov[ic++].iov_len = NalLength; + VideoPosition += NalLength; + h264_printf(20, " pts=%llu\n", VideoPts); + iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + ssize_t l = writev(call->fd, iov, ic); + if (l < 0) + return l; + len += l; + VideoPts = INVALID_PTS_VALUE; + } + } + while (NalStart < SampleSize); + if (len < 0) + { + h264_err("error writing data errno = %d\n", errno); + h264_err("%s\n", strerror(errno)); + } + h264_printf(10, "< len %d\n", len); + return len; +} + +static int writeReverseData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + h264_printf(10, "\n"); + if (call == NULL) + { + h264_err("call data is NULL...\n"); + return 0; + } + h264_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + h264_err("NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + h264_err("file pointer < 0. ignoring ...\n"); + return 0; + } + return 0; +} +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "h264", + eVideo, + "V_MPEG4/ISO/AVC", + VIDEO_ENCODING_H264, + -1, + -1 +}; + +struct Writer_s WriterVideoH264 = +{ + &reset, + &writeData, + &writeReverseData, + &caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/mp3.c b/libeplayer3-arm/output/writer/sh4/mp3.c new file mode 100644 index 0000000..d3f2f4f --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/mp3.c @@ -0,0 +1,178 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define MP3_DEBUG +#else +#define MP3_SILENT +#endif + +#ifdef MP3_DEBUG + +static short debug_level = 0; + +#define mp3_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mp3_printf(level, fmt, x...) +#endif + +#ifndef MP3_SILENT +#define mp3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mp3_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + mp3_printf(10, "\n"); + if (call == NULL) + { + mp3_err("call data is NULL...\n"); + return 0; + } + mp3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + mp3_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + mp3_err("file pointer < 0. ignoring ...\n"); + return 0; + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + int len = writev(call->fd, iov, 2); + mp3_printf(10, "mp3_Write-< len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_mp3 = +{ + "mp3", + eAudio, + "A_MP3", + AUDIO_ENCODING_MP3 +}; + +struct Writer_s WriterAudioMP3 = +{ + &reset, + &writeData, + NULL, + &caps_mp3 +}; + +static WriterCaps_t caps_mpegl3 = +{ + "mpeg/l3", + eAudio, + "A_MPEG/L3", + AUDIO_ENCODING_MPEG2 +}; + +struct Writer_s WriterAudioMPEGL3 = +{ + &reset, + &writeData, + NULL, + &caps_mpegl3 +}; + +static WriterCaps_t caps_vorbis = +{ + "vorbis", + eAudio, + "A_VORBIS", + AUDIO_ENCODING_VORBIS +}; + +struct Writer_s WriterAudioVORBIS = +{ + &reset, + &writeData, + NULL, + &caps_vorbis +}; + diff --git a/libeplayer3-arm/output/writer/sh4/mpeg2.c b/libeplayer3-arm/output/writer/sh4/mpeg2.c new file mode 100644 index 0000000..123f9dc --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/mpeg2.c @@ -0,0 +1,181 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define MPEG2_DEBUG +#else +#define MPEG2_SILENT +#endif + +#ifdef MPEG2_DEBUG + +static short debug_level = 0; + +#define mpeg2_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg2_printf(level, fmt, x...) +#endif + +#ifndef MPEG2_SILENT +#define mpeg2_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define mpeg2_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int len = 0; + unsigned int Position = 0; + mpeg2_printf(10, "\n"); + if (call == NULL) + { + mpeg2_err("call data is NULL...\n"); + return 0; + } + mpeg2_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + mpeg2_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + mpeg2_err("file pointer < 0. ignoring ...\n"); + return 0; + } + while (Position < call->len) + { + int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? + (call->len - Position) : MAX_PES_PACKET_SIZE; + int32_t Remaining = call->len - Position - PacketLength; + mpeg2_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0); + iov[1].iov_base = call->data + Position; + iov[1].iov_len = PacketLength; + ssize_t l = writev(call->fd, iov, 2); + if (l < 0) + { + len = l; + break; + } + len += l; + Position += PacketLength; + call->Pts = INVALID_PTS_VALUE; + } + mpeg2_printf(10, "< len %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ +static WriterCaps_t caps = +{ + "mpeg2", + eVideo, + "V_MPEG2", + VIDEO_ENCODING_AUTO, + -1, + -1, +}; + +struct Writer_s WriterVideoMPEG2 = +{ + &reset, + &writeData, + NULL, + &caps +}; + +static WriterCaps_t h264_caps = +{ + "mpges_h264", + eVideo, + "V_MPEG2/H264", + VIDEO_ENCODING_H264, + -1, + -1 +}; + +struct Writer_s WriterVideoMPEGH264 = +{ + &reset, + &writeData, + NULL, + &h264_caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/pcm.c b/libeplayer3-arm/output/writer/sh4/pcm.c new file mode 100644 index 0000000..14710ae --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/pcm.c @@ -0,0 +1,354 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" +#include "pcm.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define PCM_DEBUG +#else +#define PCM_SILENT +#endif + +#ifdef PCM_DEBUG + +static short debug_level = 0; + +#define pcm_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define pcm_printf(level, fmt, x...) +#endif + +#ifndef PCM_SILENT +#define pcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define pcm_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static int32_t initialHeader = 1; +static uint32_t SubFrameLen = 0; +static uint32_t SubFramesPerPES = 0; + +// reference: search for TypeLpcmDVDAudio in player/frame_parser/frame_parser_audio_lpcm.cpp +static const uint8_t clpcm_prv[14] = +{ + 0xA0, //sub_stream_id + 0, 0, //resvd and UPC_EAN_ISRC stuff, unused + 0x0A, //private header length + 0, 9, //first_access_unit_pointer + 0x00, //emph,rsvd,stereo,downmix + 0x0F, //quantisation word length 1,2 + 0x0F, //audio sampling freqency 1,2 + 0, //resvd, multi channel type + 0, //bit shift on channel GR2, assignment + 0x80, //dynamic range control + 0, 0 //resvd for copyright management +}; + +static uint8_t lpcm_prv[14]; +static uint8_t breakBuffer[8192]; +static uint32_t breakBufferFillSize = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32_t uBitsPerSample, uint8_t bLittleEndian __attribute__((unused))) +{ + printf("rate: %d ch: %d bits: %d (%d bps)\n", + uSampleRate/*Format->dwSamplesPerSec*/, + uNoOfChannels/*Format->wChannels*/, + uBitsPerSample/*Format->wBitsPerSample*/, + (uBitsPerSample/*Format->wBitsPerSample*/ / 8) + ); + SubFrameLen = 0; + SubFramesPerPES = 0; + breakBufferFillSize = 0; + memcpy(lpcm_prv, clpcm_prv, sizeof(lpcm_prv)); + //figure out size of subframe + //and set up sample rate + switch (uSampleRate) + { + case 48000: + SubFrameLen = 40; + break; + case 96000: + lpcm_prv[8] |= 0x10; + SubFrameLen = 80; + break; + case 192000: + lpcm_prv[8] |= 0x20; + SubFrameLen = 160; + break; + case 44100: + lpcm_prv[8] |= 0x80; + SubFrameLen = 40; + break; + case 88200: + lpcm_prv[8] |= 0x90; + SubFrameLen = 80; + break; + case 176400: + lpcm_prv[8] |= 0xA0; + SubFrameLen = 160; + break; + default: + break; + } + SubFrameLen *= uNoOfChannels; + SubFrameLen *= (uBitsPerSample / 8); + //rewrite PES size to have as many complete subframes per PES as we can + // FIXME: PES header size was hardcoded to 18 in previous code. Actual size returned by InsertPesHeader is 14. + SubFramesPerPES = ((2048 - 18) - sizeof(lpcm_prv)) / SubFrameLen; + SubFrameLen *= SubFramesPerPES; + //set number of channels + lpcm_prv[10] = uNoOfChannels - 1; + switch (uBitsPerSample) + { + case 24: + lpcm_prv[7] |= 0x20; + case 16: + break; + default: + printf("inappropriate bits per sample (%d) - must be 16 or 24\n", uBitsPerSample); + return 1; + } + return 0; +} + +static int32_t reset() +{ + initialHeader = 1; + return 0; +} + +static int32_t writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + pcm_printf(10, "\n"); + if (!call) + { + pcm_err("call data is NULL...\n"); + return 0; + } + pcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) + { + pcm_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + pcm_err("file pointer < 0. ignoring ...\n"); + return 0; + } + pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; + if (initialHeader) + { + uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id; + uint8_t LE = 0; + switch (codecID) + { + case AV_CODEC_ID_PCM_S8: + case AV_CODEC_ID_PCM_U8: + break; + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_U16LE: + LE = 1; + case AV_CODEC_ID_PCM_S16BE: + case AV_CODEC_ID_PCM_U16BE: + break; + case AV_CODEC_ID_PCM_S24LE: + case AV_CODEC_ID_PCM_U24LE: + LE = 1; + case AV_CODEC_ID_PCM_S24BE: + case AV_CODEC_ID_PCM_U24BE: + break; + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_U32LE: + LE = 1; + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_U32BE: + break; + default: + break; + } + initialHeader = 0; + prepareClipPlay(pcmPrivateData->channels, pcmPrivateData->sample_rate, pcmPrivateData->bits_per_coded_sample, LE); + } + uint8_t *buffer = call->data; + uint32_t size = call->len; + uint32_t n; + uint8_t *injectBuffer = malloc(SubFrameLen); + uint32_t pos; + for (pos = 0; pos < size;) + { + //printf("PCM %s - Position=%d\n", __FUNCTION__, pos); + if ((size - pos) < SubFrameLen) + { + breakBufferFillSize = size - pos; + memcpy(breakBuffer, &buffer[pos], sizeof(uint8_t) * breakBufferFillSize); + //printf("PCM %s - Unplayed=%d\n", __FUNCTION__, breakBufferFillSize); + break; + } + //get first PES's worth + if (breakBufferFillSize > 0) + { + memcpy(injectBuffer, breakBuffer, sizeof(uint8_t)*breakBufferFillSize); + memcpy(&injectBuffer[breakBufferFillSize], &buffer[pos], sizeof(unsigned char) * (SubFrameLen - breakBufferFillSize)); + pos += (SubFrameLen - breakBufferFillSize); + breakBufferFillSize = 0; + } + else + { + memcpy(injectBuffer, &buffer[pos], sizeof(uint8_t)*SubFrameLen); + pos += SubFrameLen; + } + struct iovec iov[3]; + iov[0].iov_base = PesHeader; + iov[1].iov_base = lpcm_prv; + iov[1].iov_len = sizeof(lpcm_prv); + iov[2].iov_base = injectBuffer; + iov[2].iov_len = SubFrameLen; + //write the PCM data + if (16 == pcmPrivateData->bits_per_coded_sample) + { + for (n = 0; n < SubFrameLen; n += 2) + { + uint8_t tmp; + tmp = injectBuffer[n]; + injectBuffer[n] = injectBuffer[n + 1]; + injectBuffer[n + 1] = tmp; + } + } + else + { + // 0 1 2 3 4 5 6 7 8 9 10 11 + // A1c A1b A1a-B1c B1b B1a-A2c A2b A2a-B2c B2b B2a + // to A1a A1b B1a B1b.A2a A2b B2a B2b-A1c B1c A2c B2c + for (n = 0; n < SubFrameLen; n += 12) + { + unsigned char t, *p = &injectBuffer[n]; + t = p[0]; + p[ 0] = p[ 2]; + p[ 2] = p[ 5]; + p[ 5] = p[ 7]; + p[ 7] = p[11]; + p[11] = p[ 9]; + p[ 9] = p[ 3]; + p[ 3] = p[ 4]; + p[ 4] = p[ 8]; + p[ 8] = t; + } + } + //increment err... subframe count? + lpcm_prv[1] = ((lpcm_prv[1] + SubFramesPerPES) & 0x1F); + iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len + iov[2].iov_len, PCM_PES_START_CODE, call->Pts, 0); + int32_t len = writev(call->fd, iov, 3); + if (len < 0) + { + break; + } + } + free(injectBuffer); + return size; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_pcm = +{ + "pcm", + eAudio, + "A_PCM", + AUDIO_ENCODING_LPCMA +}; + +struct Writer_s WriterAudioPCM = +{ + &reset, + &writeData, + NULL, + &caps_pcm +}; + +static WriterCaps_t caps_ipcm = +{ + "ipcm", + eAudio, + "A_IPCM", + AUDIO_ENCODING_LPCMA +}; + +struct Writer_s WriterAudioIPCM = +{ + &reset, + &writeData, + NULL, + &caps_ipcm +}; diff --git a/libeplayer3-arm/output/writer/sh4/pes.c b/libeplayer3-arm/output/writer/sh4/pes.c new file mode 100644 index 0000000..5cc56bb --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/pes.c @@ -0,0 +1,154 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +/* ***************************** */ +/* Types */ +/* ***************************** */ + + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size) +{ + BitPacker_t ld2 = {data, 0, 32}; + int i; + PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8); + PutBits(&ld2, payload_size & 0xff, 8); + PutBits(&ld2, (payload_size >> 8) & 0xff, 8); + PutBits(&ld2, (payload_size >> 16) & 0xff, 8); + for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++) + PutBits(&ld2, 0, 8); + FlushBits(&ld2); + return PES_PRIVATE_DATA_LENGTH + 1; +} + +int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code) +{ + BitPacker_t ld2 = {data, 0, 32}; + if (size > (MAX_PES_PACKET_SIZE - 13)) + { + size = -1; // unbounded + } + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x1, 8); // Start Code + PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream + //4 + if (-1 == size) + { + PutBits(&ld2, 0x0, 16); + } + else + { + PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length + } + //6 = 4+2 + PutBits(&ld2, 0x2, 2); // 10 + PutBits(&ld2, 0x0, 2); // PES_Scrambling_control + PutBits(&ld2, 0x0, 1); // PES_Priority + PutBits(&ld2, 0x0, 1); // data_alignment_indicator + PutBits(&ld2, 0x0, 1); // Copyright + PutBits(&ld2, 0x0, 1); // Original or Copy + //7 = 6+1 + if (pts != INVALID_PTS_VALUE) + { + PutBits(&ld2, 0x2, 2); + } + else + { + PutBits(&ld2, 0x0, 2); // PTS_DTS flag + } + PutBits(&ld2, 0x0, 1); // ESCR_flag + PutBits(&ld2, 0x0, 1); // ES_rate_flag + PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag + PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag + PutBits(&ld2, 0x0, 1); // PES_CRC_flag + PutBits(&ld2, 0x0, 1); // PES_extension_flag + //8 = 7+1 + if (pts != INVALID_PTS_VALUE) + PutBits(&ld2, 0x5, 8); + else + PutBits(&ld2, 0x0, 8); // PES_header_data_length + //9 = 8+1 + if (pts != INVALID_PTS_VALUE) + { + PutBits(&ld2, 0x2, 4); + PutBits(&ld2, (pts >> 30) & 0x7, 3); + PutBits(&ld2, 0x1, 1); + PutBits(&ld2, (pts >> 15) & 0x7fff, 15); + PutBits(&ld2, 0x1, 1); + PutBits(&ld2, pts & 0x7fff, 15); + PutBits(&ld2, 0x1, 1); + } + //14 = 9+5 + if (pic_start_code) + { + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x0, 8); + PutBits(&ld2, 0x1, 8); // Start Code + PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start + PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code) + //14 + 4 = 18 + } + FlushBits(&ld2); + return (ld2.Ptr - data); +} diff --git a/libeplayer3-arm/output/writer/sh4/vc1.c b/libeplayer3-arm/output/writer/sh4/vc1.c new file mode 100644 index 0000000..cde188d --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/vc1.c @@ -0,0 +1,263 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define WMV3_PRIVATE_DATA_LENGTH 4 + +#define METADATA_STRUCT_A_START 12 +#define METADATA_STRUCT_B_START 24 +#define METADATA_STRUCT_B_FRAMERATE_START 32 +#define METADATA_STRUCT_C_START 8 + + +#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80 +#define VC1_FRAME_START_CODE 0x0d + +#ifdef SAM_WITH_DEBUG +#define VC1_DEBUG +#else +#define VC1_SILENT +#endif + +#ifdef VC1_DEBUG + +static short debug_level = 0; + +#define vc1_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vc1_printf(level, fmt, x...) +#endif + +#ifndef VC1_SILENT +#define vc1_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vc1_err(fmt, x...) +#endif + + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +static const unsigned char SequenceLayerStartCode[] = {0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE}; + + +static const unsigned char Metadata[] = +{ + 0x00, 0x00, 0x00, 0xc5, + 0x04, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile*/ + 0x00, 0x00, 0x00, 0x00, /* Struct A */ + 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, /* Struct B */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; +static unsigned char FrameHeaderSeen = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + FrameHeaderSeen = 0; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; + vc1_printf(10, "\n"); + if (call == NULL) + { + vc1_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + vc1_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + vc1_err("file pointer < 0. ignoring ...\n"); + return 0; + } + vc1_printf(10, "VideoPts %lld\n", call->Pts); + vc1_printf(10, "Got Private Size %d\n", call->private_size); + if (initialHeader) + { + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + unsigned char PesPayload[128]; + unsigned char *PesPtr; + unsigned int crazyFramerate = 0; + struct iovec iov[2]; + vc1_printf(10, "Framerate: %u\n", call->FrameRate); + vc1_printf(10, "biWidth: %d\n", call->Width); + vc1_printf(10, "biHeight: %d\n", call->Height); + crazyFramerate = ((10000000.0 / call->FrameRate) * 1000.0); + vc1_printf(10, "crazyFramerate: %u\n", crazyFramerate); + memset(PesPayload, 0, sizeof(PesPayload)); + PesPtr = PesPayload; + memcpy(PesPtr, SequenceLayerStartCode, sizeof(SequenceLayerStartCode)); + PesPtr += sizeof(SequenceLayerStartCode); + memcpy(PesPtr, Metadata, sizeof(Metadata)); + PesPtr += METADATA_STRUCT_C_START; + PesPtr += WMV3_PRIVATE_DATA_LENGTH; + /* Metadata Header Struct A */ + *PesPtr++ = (call->Height >> 0) & 0xff; + *PesPtr++ = (call->Height >> 8) & 0xff; + *PesPtr++ = (call->Height >> 16) & 0xff; + *PesPtr++ = call->Height >> 24; + *PesPtr++ = (call->Width >> 0) & 0xff; + *PesPtr++ = (call->Width >> 8) & 0xff; + *PesPtr++ = (call->Width >> 16) & 0xff; + *PesPtr++ = call->Width >> 24; + PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */ + *PesPtr++ = (crazyFramerate >> 0) & 0xff; + *PesPtr++ = (crazyFramerate >> 8) & 0xff; + *PesPtr++ = (crazyFramerate >> 16) & 0xff; + *PesPtr++ = crazyFramerate >> 24; + iov[0].iov_base = PesHeader; + iov[1].iov_base = PesPayload; + iov[1].iov_len = PesPtr - PesPayload; + iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + len = writev(call->fd, iov, 2); + /* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */ + iov[0].iov_base = PesHeader; + iov[1].iov_base = call->private_data; + iov[1].iov_len = call->private_size; + iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + len = writev(call->fd, iov, 2); + initialHeader = 0; + } + if (call->len > 0 && call->data) + { + uint32_t Position = 0; + uint8_t insertSampleHeader = 1; + while (Position < call->len) + { + int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? + (call->len - Position) : MAX_PES_PACKET_SIZE; + int32_t Remaining = call->len - Position - PacketLength; + vc1_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + uint8_t PesHeader[PES_MAX_HEADER_SIZE]; + int32_t HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0); + if (insertSampleHeader) + { + const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE}; + if (!FrameHeaderSeen && (call->len > 3) && (memcmp(call->data, Vc1FrameStartCode, 4) == 0)) + { + FrameHeaderSeen = 1; + } + if (!FrameHeaderSeen) + { + memcpy(&PesHeader[HeaderLength], Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); + HeaderLength += sizeof(Vc1FrameStartCode); + } + insertSampleHeader = 0; + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = HeaderLength; + iov[1].iov_base = call->data + Position; + iov[1].iov_len = PacketLength; + ssize_t l = writev(call->fd, iov, 2); + if (l < 0) + { + len = l; + break; + } + len += l; + Position += PacketLength; + call->Pts = INVALID_PTS_VALUE; + } + } + vc1_printf(10, "< %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "vc1", + eVideo, + "V_VC1", + VIDEO_ENCODING_VC1, + -1, + -1 +}; + +struct Writer_s WriterVideoVC1 = +{ + &reset, + &writeData, + NULL, + &caps +}; + diff --git a/libeplayer3-arm/output/writer/sh4/vorbis.c b/libeplayer3-arm/output/writer/sh4/vorbis.c new file mode 100644 index 0000000..34d8a82 --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/vorbis.c @@ -0,0 +1,146 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "stm_ioctls.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#ifdef SAM_WITH_DEBUG +#define VORBIS_DEBUG +#else +#define VORBIS_SILENT +#endif + +#ifdef VORBIS_DEBUG + +static short debug_level = 1; + +#define vorbis_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vorbis_printf(level, fmt, x...) +#endif + +#ifndef VORBIS_SILENT +#define vorbis_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define vorbis_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + vorbis_printf(10, "\n"); + if (call == NULL) + { + vorbis_err("call data is NULL...\n"); + return 0; + } + vorbis_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + vorbis_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + vorbis_err("file pointer < 0. ignoring ...\n"); + return 0; + } + int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + unsigned char *PacketStart = malloc(call->len + HeaderLength); + memcpy(PacketStart, PesHeader, HeaderLength); + memcpy(PacketStart + HeaderLength, call->data, call->len); + int len = write(call->fd, PacketStart, call->len + HeaderLength); + free(PacketStart); + vorbis_printf(10, "vorbis_Write-< len=%d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps_vorbis = +{ + "vorbis", + eAudio, + "A_VORBIS", + AUDIO_ENCODING_VORBIS, + -1, + -1 +}; + +struct Writer_s WriterAudioVORBIS = +{ + &reset, + &writeData, + NULL, + &caps_vorbis +}; diff --git a/libeplayer3-arm/output/writer/sh4/wma.c b/libeplayer3-arm/output/writer/sh4/wma.c new file mode 100644 index 0000000..bd577bb --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/wma.c @@ -0,0 +1,191 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define WMA_DEBUG +#else +#define WMA_SILENT +#endif + +#ifdef WMA_DEBUG + +static short debug_level = 0; + +#define wma_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wma_printf(level, fmt, x...) +#endif + +#ifndef WMA_SILENT +#define wma_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wma_err(fmt, x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static int initialHeader = 1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; + wma_printf(10, "\n"); + if (call == NULL) + { + wma_err("call data is NULL...\n"); + return 0; + } + wma_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) + { + wma_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + wma_err("file pointer < 0. ignoring ...\n"); + return 0; + } + if (initialHeader) + { + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if ((call->private_size <= 0) || (call->private_data == NULL)) + { + wma_err("private NULL.\n"); + return -1; + } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0); + iov[1].iov_base = call->private_data; + iov[1].iov_len = call->private_size; + len = writev(call->fd, iov, 2); + initialHeader = 0; + } + if (len > -1 && call->len > 0 && call->data) + { + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + struct iovec iov[2]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + iov[1].iov_base = call->data; + iov[1].iov_len = call->len; + ssize_t l = writev(call->fd, iov, 2); + len = (l > -1) ? len + l : l; + } + wma_printf(10, "wma < %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t capsWMAPRO = +{ + "wma/pro", + eAudio, + "A_WMA/PRO", + AUDIO_ENCODING_WMA, + -1, + -1 +}; + +struct Writer_s WriterAudioWMAPRO = +{ + &reset, + &writeData, + NULL, + &capsWMAPRO +}; + + +static WriterCaps_t capsWMA = +{ + "wma", + eAudio, + "A_WMA", + AUDIO_ENCODING_WMA, + -1, + -1 +}; + +struct Writer_s WriterAudioWMA = +{ + &reset, + &writeData, + NULL, + &capsWMA +}; diff --git a/libeplayer3-arm/output/writer/sh4/wmv.c b/libeplayer3-arm/output/writer/sh4/wmv.c new file mode 100644 index 0000000..782d83b --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/wmv.c @@ -0,0 +1,254 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 based on linuxdvb.c code from libeplayer2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "debug.h" +#include "misc.h" +#include "pes.h" +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define WMV3_PRIVATE_DATA_LENGTH 4 + +#define METADATA_STRUCT_A_START 12 +#define METADATA_STRUCT_B_START 24 +#define METADATA_STRUCT_B_FRAMERATE_START 32 +#define METADATA_STRUCT_C_START 8 + +#ifdef SAM_WITH_DEBUG +#define WMV_DEBUG +#else +#define WMV_SILENT +#endif + +#ifdef WMV_DEBUG + +static short debug_level = 0; + +#define wmv_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wmv_printf(level, fmt, x...) +#endif + +#ifndef WMV_SILENT +#define wmv_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define wmv_err(fmt, x...) +#endif + + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +typedef struct +{ + unsigned char privateData[WMV3_PRIVATE_DATA_LENGTH]; + unsigned int width; + unsigned int height; + unsigned int framerate; +} awmv_t; + +static const unsigned char Metadata[] = +{ + 0x00, 0x00, 0x00, 0xc5, + 0x04, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile*/ + 0x00, 0x00, 0x00, 0x00, /* Struct A */ + 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, /* Struct B */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static int initialHeader = 1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +static int reset() +{ + initialHeader = 1; + return 0; +} + +static int writeData(void *_call) +{ + WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + awmv_t private_data; + int len = 0; + wmv_printf(10, "\n"); + if (call == NULL) + { + wmv_err("call data is NULL...\n"); + return 0; + } + if ((call->data == NULL) || (call->len <= 0)) + { + wmv_err("parsing NULL Data. ignoring...\n"); + return 0; + } + if (call->fd < 0) + { + wmv_err("file pointer < 0. ignoring ...\n"); + return 0; + } + wmv_printf(10, "VideoPts %lld\n", call->Pts); + wmv_printf(10, "Got Private Size %d\n", call->private_size); + memcpy(private_data.privateData, call->private_data, + call->private_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : call->private_size); + private_data.width = call->Width; + private_data.height = call->Height; + private_data.framerate = call->FrameRate; +#define PES_MIN_HEADER_SIZE 9 + if (initialHeader) + { + unsigned char PesPacket[PES_MIN_HEADER_SIZE + 128]; + unsigned char *PesPtr; + unsigned int MetadataLength; + unsigned int crazyFramerate = 0; + wmv_printf(10, "Framerate: %u\n", private_data.framerate); + wmv_printf(10, "biWidth: %d\n", private_data.width); + wmv_printf(10, "biHeight: %d\n", private_data.height); + crazyFramerate = ((10000000.0 / private_data.framerate) * 1000.0); + wmv_printf(10, "crazyFramerate: %u\n", crazyFramerate); + PesPtr = &PesPacket[PES_MIN_HEADER_SIZE]; + memcpy(PesPtr, Metadata, sizeof(Metadata)); + PesPtr += METADATA_STRUCT_C_START; + memcpy(PesPtr, private_data.privateData, WMV3_PRIVATE_DATA_LENGTH); + PesPtr += WMV3_PRIVATE_DATA_LENGTH; + /* Metadata Header Struct A */ + *PesPtr++ = (private_data.height >> 0) & 0xff; + *PesPtr++ = (private_data.height >> 8) & 0xff; + *PesPtr++ = (private_data.height >> 16) & 0xff; + *PesPtr++ = private_data.height >> 24; + *PesPtr++ = (private_data.width >> 0) & 0xff; + *PesPtr++ = (private_data.width >> 8) & 0xff; + *PesPtr++ = (private_data.width >> 16) & 0xff; + *PesPtr++ = private_data.width >> 24; + PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */ + *PesPtr++ = (crazyFramerate >> 0) & 0xff; + *PesPtr++ = (crazyFramerate >> 8) & 0xff; + *PesPtr++ = (crazyFramerate >> 16) & 0xff; + *PesPtr++ = crazyFramerate >> 24; + MetadataLength = PesPtr - &PesPacket[PES_MIN_HEADER_SIZE]; + int HeaderLength = InsertPesHeader(PesPacket, MetadataLength, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + len = write(call->fd, PesPacket, HeaderLength + MetadataLength); + initialHeader = 0; + } + if (call->len > 0 && call->data) + { + unsigned int Position = 0; + unsigned char insertSampleHeader = 1; + while (Position < call->len) + { + int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? + (call->len - Position) : MAX_PES_PACKET_SIZE; + int Remaining = call->len - Position - PacketLength; + wmv_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + memset(PesHeader, '0', PES_MAX_HEADER_SIZE); + int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0); + unsigned char *PacketStart; + if (insertSampleHeader) + { + unsigned int PesLength; + unsigned int PrivateHeaderLength; + PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], + call->len); + /* Update PesLength */ + PesLength = PesHeader[PES_LENGTH_BYTE_0] + + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength; + PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff; + PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; + PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; + PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; + HeaderLength += PrivateHeaderLength; + insertSampleHeader = 0; + } + PacketStart = malloc(call->len + HeaderLength); + memcpy(PacketStart, PesHeader, HeaderLength); + memcpy(PacketStart + HeaderLength, call->data + Position, PacketLength); + len = write(call->fd, PacketStart, PacketLength + HeaderLength); + free(PacketStart); + Position += PacketLength; + call->Pts = INVALID_PTS_VALUE; + } + } + wmv_printf(10, "< %d\n", len); + return len; +} + +/* ***************************** */ +/* Writer Definition */ +/* ***************************** */ + +static WriterCaps_t caps = +{ + "wmv", + eVideo, + "V_WMV", + VIDEO_ENCODING_WMV, + -1, + -1 +}; + +struct Writer_s WriterVideoWMV = +{ + &reset, + &writeData, + NULL, + &caps +}; diff --git a/libeplayer3-arm/output/writer/sh4/writer.c b/libeplayer3-arm/output/writer/sh4/writer.c new file mode 100644 index 0000000..6d7e9ee --- /dev/null +++ b/libeplayer3-arm/output/writer/sh4/writer.c @@ -0,0 +1,144 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include "writer.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#ifdef SAM_WITH_DEBUG +#define WRITER_DEBUG +#else +#define WRITER_SILENT +#endif + +#ifdef WRITER_DEBUG + +static short debug_level = 0; + +#define writer_printf(level, x...) do { \ + if (debug_level >= level) printf(x); } while (0) +#else +#define writer_printf(level, x...) +#endif + +#ifndef WRITER_SILENT +#define writer_err(x...) do { printf(x); } while (0) +#else +#define writer_err(x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Writer_t *AvailableWriter[] = +{ + &WriterAudioIPCM, + &WriterAudioPCM, + &WriterAudioMP3, + &WriterAudioMPEGL3, + &WriterAudioAC3, + &WriterAudioAAC, + &WriterAudioDTS, + &WriterAudioWMA, + &WriterAudioVORBIS, + + &WriterVideoMPEG2, + &WriterVideoMPEGH264, + &WriterVideoH264, + &WriterVideoDIVX, + &WriterVideoFOURCC, + &WriterVideoMSCOMP, + &WriterVideoWMV, + &WriterVideoH263, + &WriterVideoFLV, + &WriterVideoVC1, + NULL +}; + +// &WriterAudioFLAC, + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +Writer_t *getWriter(char *encoding) +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0) + { + writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, encoding); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding); + return NULL; +} + +Writer_t *getDefaultVideoWriter() +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0) + { + writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; +} + +Writer_t *getDefaultAudioWriter() +{ + int i; + for (i = 0; AvailableWriter[i] != NULL; i++) + { + if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0) + { + writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name); + return AvailableWriter[i]; + } + } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; +} + diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c new file mode 100644 index 0000000..19dfb6b --- /dev/null +++ b/libeplayer3-arm/playback/playback.c @@ -0,0 +1,700 @@ +/* + * GPL + * duckbox 2010 + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "playback.h" +#include "common.h" +#include "misc.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +// SULGE DEBUG +//#define SAM_WITH_DEBUG + +#ifdef SAM_WITH_DEBUG +#define PLAYBACK_DEBUG +#else +#define PLAYBACK_SILENT +#endif + +static short debug_level = 20; + +#ifdef PLAYBACK_DEBUG +#define playback_printf(level, fmt, x...) do { \ + if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define playback_printf(level, fmt, x...) +#endif + +#ifndef PLAYBACK_SILENT +#define playback_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define playback_err(fmt, x...) +#endif + +#define cERR_PLAYBACK_NO_ERROR 0 +#define cERR_PLAYBACK_ERROR -1 + +#define cMaxSpeed_ff 128 /* fixme: revise */ +#define cMaxSpeed_fr -320 /* fixme: revise */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static pthread_t supervisorThread; +static int hasThreadStarted = 0; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ +static int32_t PlaybackTerminate(Context_t *context); + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ +int8_t PlaybackDieNow(int8_t val) +{ + static int8_t dieNow = 0; + if (val) + { + dieNow = 1; + } + return dieNow; +} + +/* **************************** */ +/* Supervisor Thread */ +/* **************************** */ + +static void SupervisorThread(Context_t *context) +{ + hasThreadStarted = 1; + playback_printf(10, ">\n"); + while (context && context->playback && context->playback->isPlaying && !context->playback->abortRequested) + usleep(100000); + playback_printf(10, "<\n"); + hasThreadStarted = 2; + PlaybackTerminate(context); + playback_printf(0, "terminating\n"); + hasThreadStarted = 0; +} + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int PlaybackStop(Context_t *context); + +static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) +{ + if (context->playback->isPlaying) + { + PlaybackStop(context); + } + char *uri = pFiles->szFirstFile; + playback_printf(10, "URI=%s\n", uri); + if (context->playback->isPlaying) + { + // shouldn't happen + playback_err("playback already running\n"); + return cERR_PLAYBACK_ERROR; + } + char *extension = NULL; + context->playback->uri = strdup(uri); + context->playback->isFile = 0; + context->playback->isHttp = 0; + if (!strncmp("file://", uri, 7) || !strncmp("myts://", uri, 7)) + { + context->playback->isFile = 1; + if (!strncmp("myts://", uri, 7)) + { + memcpy(context->playback->uri, "file", 4); + context->playback->noprobe = 1; + } + else + { + context->playback->noprobe = 0; + } + extension = getExtension(context->playback->uri + 7); + if (!extension) + { + playback_err("Wrong extension (%s)\n", context->playback->uri + 7); + return cERR_PLAYBACK_ERROR; + } + } + else if (strstr(uri, "://")) + { + context->playback->isHttp = 1; + extension = "mp3"; + if (!strncmp("mms://", uri, 6)) + { + // mms is in reality called rtsp, and ffmpeg expects this + char *tUri = (char *)malloc(strlen(uri) + 2); + strncpy(tUri + 1, uri, strlen(uri) + 1); + strncpy(tUri, "rtsp", 4); + free(context->playback->uri); + context->playback->uri = tUri; + } + } + else + { + playback_err("Unknown stream (%s)\n", uri); + return cERR_PLAYBACK_ERROR; + } + pFiles->szFirstFile = context->playback->uri; + if ((context->container->Command(context, CONTAINER_ADD, extension) < 0) + || (!context->container->selectedContainer) + || (context->container->selectedContainer->Command(context, CONTAINER_INIT, pFiles) < 0)) + { + playback_err("CONTAINER_ADD failed\n"); + return cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value 0\n"); + return cERR_PLAYBACK_NO_ERROR; +} + +static int PlaybackClose(Context_t *context) +{ + int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->container->Command(context, CONTAINER_DEL, NULL) < 0) + { + playback_err("container delete failed\n"); + } + context->manager->audio->Command(context, MANAGER_DEL, NULL); + context->manager->video->Command(context, MANAGER_DEL, NULL); + context->playback->isPaused = 0; + context->playback->isPlaying = 0; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 0; + if (context->playback->uri) + { + free(context->playback->uri); + context->playback->uri = NULL; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int PlaybackPlay(Context_t *context) +{ + pthread_attr_t attr; + int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (!context->playback->isPlaying) + { + context->playback->AVSync = 1; + context->output->Command(context, OUTPUT_AVSYNC, NULL); + context->playback->isCreationPhase = 1; // allows the created thread to go into wait mode + ret = context->output->Command(context, OUTPUT_PLAY, NULL); + if (ret != 0) + { + playback_err("OUTPUT_PLAY failed!\n"); + playback_err("clearing isCreationPhase!\n"); + context->playback->isCreationPhase = 0; // allow thread to go into next state + context->playback->isPlaying = 0; + context->playback->isPaused = 0; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 0; + context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL); + } + else + { + context->playback->isPlaying = 1; + context->playback->isPaused = 0; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 1; + if (hasThreadStarted == 0) + { + int error; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if ((error = pthread_create(&supervisorThread, &attr, (void *) &SupervisorThread, context)) != 0) + { + playback_printf(10, "Error creating thread, error:%d:%s\n", error, strerror(error)); + ret = cERR_PLAYBACK_ERROR; + } + else + { + playback_printf(10, "Created thread\n"); + } + } + playback_printf(10, "clearing isCreationPhase!\n"); + context->playback->isCreationPhase = 0; // allow thread to go into next state + ret = context->container->selectedContainer->Command(context, CONTAINER_PLAY, NULL); + if (ret != 0) + { + playback_err("CONTAINER_PLAY failed!\n"); + } + } + } + else + { + playback_err("playback already running\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int PlaybackPause(Context_t *context) +{ + int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->playback->isPlaying && !context->playback->isPaused) + { + if (context->playback->SlowMotion) + context->output->Command(context, OUTPUT_CLEAR, NULL); + context->output->Command(context, OUTPUT_PAUSE, NULL); + context->playback->isPaused = 1; + //context->playback->isPlaying = 1; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 1; + } + else + { + playback_err("playback not playing or already in pause mode\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackContinue(Context_t *context) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->playback->isPlaying && + (context->playback->isPaused || context->playback->isForwarding || + context->playback->BackWard || context->playback->SlowMotion)) + { + if (context->playback->SlowMotion) + context->output->Command(context, OUTPUT_CLEAR, NULL); + context->output->Command(context, OUTPUT_CONTINUE, NULL); + context->playback->isPaused = 0; + //context->playback->isPlaying = 1; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 1; + } + else + { + playback_err("continue not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackStop(Context_t *context) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + int wait_time = 20; + playback_printf(10, "\n"); + PlaybackDieNow(1); + if (context && context->playback && context->playback->isPlaying) + { + context->playback->isPaused = 0; + context->playback->isPlaying = 0; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 0; + context->output->Command(context, OUTPUT_STOP, NULL); + context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL); + } + else + { + playback_err("stop not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + while ((hasThreadStarted == 1) && (--wait_time) > 0) + { + playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time); + usleep(100000); + } + if (wait_time == 0) + { + playback_err("Timeout waiting for thread!\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackTerminate(Context_t *context) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + int wait_time = 20; + playback_printf(20, "\n"); + PlaybackDieNow(1); + if (context && context->playback && context->playback->isPlaying) + { + //First Flush and than delete container, else e2 cant read length of file anymore + if (context->output->Command(context, OUTPUT_FLUSH, NULL) < 0) + { + playback_err("failed to flush output.\n"); + } + context->playback->isPaused = 0; + context->playback->isPlaying = 0; + context->playback->isForwarding = 0; + context->playback->BackWard = 0; + context->playback->SlowMotion = 0; + context->playback->Speed = 0; + context->output->Command(context, OUTPUT_STOP, NULL); + ret = context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL); + } + else + { + playback_err("%p %p %d\n", context, context->playback, context->playback->isPlaying); + /* fixme: konfetti: we should return an error here but this seems to be a condition which + * can happen and is not a real error, which leads to a dead neutrino. should investigate + * here later. + */ + } + while ((hasThreadStarted == 1) && (--wait_time) > 0) + { + playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time); + usleep(100000); + } + if (wait_time == 0) + { + playback_err("Timeout waiting for thread!\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(20, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackSeek(Context_t *context, int64_t *pos, uint8_t absolute) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "pos: %lldd\n", *pos); + if (context->playback->isPlaying && !context->playback->isForwarding && !context->playback->BackWard && !context->playback->SlowMotion && !context->playback->isPaused) + { + context->playback->isSeeking = 1; + context->output->Command(context, OUTPUT_CLEAR, NULL); + if (absolute) + { + context->container->selectedContainer->Command(context, CONTAINER_SEEK_ABS, pos); + } + else + { + context->container->selectedContainer->Command(context, CONTAINER_SEEK, pos); + } + context->playback->isSeeking = 0; + } + else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackPts(Context_t *context, int64_t *pts) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *pts = 0; + if (context->playback->isPlaying) + { + ret = context->output->Command(context, OUTPUT_PTS, pts); + } + else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(20, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackGetFrameCount(Context_t *context, int64_t *frameCount) +{ + int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *frameCount = 0; + if (context->playback->isPlaying) + { + ret = context->output->Command(context, OUTPUT_GET_FRAME_COUNT, frameCount); + } + else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(20, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackLength(Context_t *context, int64_t *length) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *length = -1; + if (context->playback->isPlaying) + { + if (context->container && context->container->selectedContainer) + { + context->container->selectedContainer->Command(context, CONTAINER_LENGTH, length); + } + } + else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(20, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + int32_t curtrackid = 0; + int32_t nextrackid = 0; + playback_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) + { + if (context->manager && context->manager->audio) + { + context->manager->audio->Command(context, MANAGER_GET, &curtrackid); + context->manager->audio->Command(context, MANAGER_SET, track); + context->manager->audio->Command(context, MANAGER_GET, &nextrackid); + } + else + { + playback_err("switch audio not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + if (nextrackid != curtrackid) + { + //PlaybackPause(context); + if (context->output && context->output->audio) + { + context->output->audio->Command(context, OUTPUT_SWITCH, (void *)"audio"); + } + if (context->container && context->container->selectedContainer) + { + context->container->selectedContainer->Command(context, CONTAINER_SWITCH_AUDIO, &nextrackid); + } + //PlaybackContinue(context); + } + } + else + { + playback_err("switch audio not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + int32_t curtrackid = -1; + int32_t nextrackid = -1; + playback_printf(10, "Track: %d\n", *track); + if (context && context->playback && context->playback->isPlaying) + { + if (context->manager && context->manager->subtitle) + { + context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid); + context->manager->subtitle->Command(context, MANAGER_SET, track); + context->manager->subtitle->Command(context, MANAGER_GET, &nextrackid); + if (curtrackid != nextrackid && nextrackid > -1) + { + if (context->output && context->output->subtitle) + { + context->output->subtitle->Command(context, OUTPUT_SWITCH, (void *)"subtitle"); + } + if (context->container && context->container->selectedContainer) + { + context->container->selectedContainer->Command(context, CONTAINER_SWITCH_SUBTITLE, &nextrackid); + } + } + } + else + { + ret = cERR_PLAYBACK_ERROR; + playback_err("no subtitle\n"); + } + } + else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t PlaybackInfo(Context_t *context, char **infoString) +{ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + /* konfetti comment: + * removed if clause here (playback running) because its + * not necessary for all container. e.g. in case of ffmpeg + * container playback must not play to get the info. + */ + if (context->container && context->container->selectedContainer) + { + context->container->selectedContainer->Command(context, CONTAINER_INFO, infoString); + } + playback_printf(10, "exiting with value %d\n", ret); + return ret; +} + +static int32_t Command(void *_context, PlaybackCmd_t command, void *argument) +{ + Context_t *context = (Context_t *) _context; /* to satisfy compiler */ + int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "Command %d\n", command); + switch (command) + { + case PLAYBACK_OPEN: + { + ret = PlaybackOpen(context, (PlayFiles_t *)argument); + break; + } + case PLAYBACK_CLOSE: + { + ret = PlaybackClose(context); + break; + } + case PLAYBACK_PLAY: + { + ret = PlaybackPlay(context); + break; + } + case PLAYBACK_STOP: + { + ret = PlaybackStop(context); + break; + } + case PLAYBACK_PAUSE: + { + ret = PlaybackPause(context); + break; + } + case PLAYBACK_CONTINUE: + { + ret = PlaybackContinue(context); + break; + } + case PLAYBACK_TERM: + { + ret = PlaybackTerminate(context); + break; + } + case PLAYBACK_SEEK: + { + ret = PlaybackSeek(context, (int64_t *)argument, 0); + break; + } + case PLAYBACK_SEEK_ABS: + { + ret = PlaybackSeek(context, (int64_t *)argument, -1); + break; + } + case PLAYBACK_PTS: + { + ret = PlaybackPts(context, (int64_t *)argument); + break; + } + case PLAYBACK_LENGTH: + { + ret = PlaybackLength(context, (int64_t *)argument); + break; + } + case PLAYBACK_SWITCH_AUDIO: + { + ret = PlaybackSwitchAudio(context, (int *)argument); + break; + } + case PLAYBACK_SWITCH_SUBTITLE: + { + ret = PlaybackSwitchSubtitle(context, (int *)argument); + break; + } + case PLAYBACK_INFO: + { + ret = PlaybackInfo(context, (char **)argument); + break; + } + case PLAYBACK_GET_FRAME_COUNT: + { + ret = PlaybackGetFrameCount(context, (uint64_t *)argument); + break; + } + default: + playback_err("PlaybackCmd %d not supported!\n", command); + ret = cERR_PLAYBACK_ERROR; + break; + } + playback_printf(20, "exiting with value %d\n", ret); + return ret; +} + +/* + * This is very unreadable and must be changed + */ +PlaybackHandler_t PlaybackHandler = +{ + "Playback", //name + -1, //fd + 0, //isFile + 0, //isHttp + 0, //isPlaying + 0, //isPaused + 0, //isForwarding + 0, //isSeeking + 0, //isCreationPhase + 0, //BackWard + 0, //SlowMotion + 0, //Speed + 0, //AVSync + 0, //isVideo + 0, //isAudio + 0, //isSubtitle + 0, //abortRequested + &Command, //Command + "", //uri + 0, //size + 0, //noprobe + 0, //isLoopMode + 0, //isTSLiveMode +};