• Jarkko Koivikko's avatar
    Automatically hide word candidate list · 839a0afe
    Jarkko Koivikko authored
    
    This change adds support for automatically hiding word candidate list
    when inactive. This feature includes the following enhancements:
    
    - Added new settings:
      * VirtualKeyboardSettings.wordCandidateList.autoHideDelay
      * VirtualKeyboardSettings.wordCandidateList.alwaysVisible
    - Automatic hiding of word candidate list when inactive and when
      autoHideDelay elapsed.
    - alwaysVisible setting restores the old functionality.
    - Added new signal selectionListsChanged() to input method, allowing
      the input method to dynamically allocate or deallocate selection
      lists.
    - HunspellInputMethod does not allocate selection list when
      dictionary cannot be loaded, or Qt::ImhNoPredictiveText is enabled.
      Also, it will no longer use pre-edit text in this case.
    - OpenWnnInputMethod does not allocate selection list if not needed.
    
    [ChangeLog] Automatically hide word candidate list when inactive.
    
    Change-Id: Ifa95ae8a7c47a96719ffdc2929601ff2ef9c0d2e
    Reviewed-by: default avatarGordan Markus <gordan.markus@pelagicore.com>
    Reviewed-by: default avatarMitch Curtis <mitch.curtis@qt.io>
    839a0afe
webmenc.c 10.20 KiB
/*
 *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "webmenc.h"
#include <limits.h>
#include <string.h>
#include "third_party/libmkv/EbmlWriter.h"
#include "third_party/libmkv/EbmlIDs.h"
void Ebml_Write(struct EbmlGlobal *glob,
                const void *buffer_in,
                unsigned long len) {
  (void) fwrite(buffer_in, 1, len, glob->stream);
#define WRITE_BUFFER(s) \
for (i = len - 1; i >= 0; i--) { \
  x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
  Ebml_Write(glob, &x, 1); \
void Ebml_Serialize(struct EbmlGlobal *glob,
                    const void *buffer_in,
                    int buffer_size,
                    unsigned long len) {
  char x;
  int i;
  /* buffer_size:
   * 1 - int8_t;
   * 2 - int16_t;
   * 3 - int32_t;
   * 4 - int64_t;
  switch (buffer_size) {
    case 1:
      WRITE_BUFFER(int8_t)
      break;
    case 2:
      WRITE_BUFFER(int16_t)
      break;
    case 4:
      WRITE_BUFFER(int32_t)
      break;
    case 8:
      WRITE_BUFFER(int64_t)
      break;
    default:
      break;
#undef WRITE_BUFFER
/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
 * one, but not a 32 bit one.
static void Ebml_SerializeUnsigned32(struct EbmlGlobal *glob,
                                     unsigned int class_id,
                                     uint64_t ui) {
  const unsigned char sizeSerialized = 4 | 0x80;
  Ebml_WriteID(glob, class_id);
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
Ebml_Serialize(glob, &ui, sizeof(ui), 4); } static void Ebml_StartSubElement(struct EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned int class_id) { const uint64_t kEbmlUnknownLength = LITERALU64(0x01FFFFFF, 0xFFFFFFFF); Ebml_WriteID(glob, class_id); *ebmlLoc = ftello(glob->stream); Ebml_Serialize(glob, &kEbmlUnknownLength, sizeof(kEbmlUnknownLength), 8); } static void Ebml_EndSubElement(struct EbmlGlobal *glob, EbmlLoc *ebmlLoc) { off_t pos; uint64_t size; /* Save the current stream pointer. */ pos = ftello(glob->stream); /* Calculate the size of this element. */ size = pos - *ebmlLoc - 8; size |= LITERALU64(0x01000000, 0x00000000); /* Seek back to the beginning of the element and write the new size. */ fseeko(glob->stream, *ebmlLoc, SEEK_SET); Ebml_Serialize(glob, &size, sizeof(size), 8); /* Reset the stream pointer. */ fseeko(glob->stream, pos, SEEK_SET); } void write_webm_seek_element(struct EbmlGlobal *ebml, unsigned int id, off_t pos) { uint64_t offset = pos - ebml->position_reference; EbmlLoc start; Ebml_StartSubElement(ebml, &start, Seek); Ebml_SerializeBinary(ebml, SeekID, id); Ebml_SerializeUnsigned64(ebml, SeekPosition, offset); Ebml_EndSubElement(ebml, &start); } void write_webm_seek_info(struct EbmlGlobal *ebml) { off_t pos; EbmlLoc start; EbmlLoc startInfo; uint64_t frame_time; char version_string[64]; /* Save the current stream pointer. */ pos = ftello(ebml->stream); if (ebml->seek_info_pos) fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET); else ebml->seek_info_pos = pos; Ebml_StartSubElement(ebml, &start, SeekHead); write_webm_seek_element(ebml, Tracks, ebml->track_pos); write_webm_seek_element(ebml, Cues, ebml->cue_pos); write_webm_seek_element(ebml, Info, ebml->segment_info_pos); Ebml_EndSubElement(ebml, &start); /* Create and write the Segment Info. */ if (ebml->debug) { strcpy(version_string, "vpxenc"); } else { strcpy(version_string, "vpxenc "); strncat(version_string, vpx_codec_version_str(),
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
sizeof(version_string) - 1 - strlen(version_string)); } frame_time = (uint64_t)1000 * ebml->framerate.den / ebml->framerate.num; ebml->segment_info_pos = ftello(ebml->stream); Ebml_StartSubElement(ebml, &startInfo, Info); Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000); Ebml_SerializeFloat(ebml, Segment_Duration, (double)(ebml->last_pts_ms + frame_time)); Ebml_SerializeString(ebml, 0x4D80, version_string); Ebml_SerializeString(ebml, 0x5741, version_string); Ebml_EndSubElement(ebml, &startInfo); } void write_webm_file_header(struct EbmlGlobal *glob, const vpx_codec_enc_cfg_t *cfg, const struct vpx_rational *fps, stereo_format_t stereo_fmt, unsigned int fourcc) { EbmlLoc start; EbmlLoc trackStart; EbmlLoc videoStart; unsigned int trackNumber = 1; uint64_t trackID = 0; unsigned int pixelWidth = cfg->g_w; unsigned int pixelHeight = cfg->g_h; /* Write the EBML header. */ Ebml_StartSubElement(glob, &start, EBML); Ebml_SerializeUnsigned(glob, EBMLVersion, 1); Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); Ebml_SerializeString(glob, DocType, "webm"); Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); Ebml_EndSubElement(glob, &start); /* Open and begin writing the segment element. */ Ebml_StartSubElement(glob, &glob->startSegment, Segment); glob->position_reference = ftello(glob->stream); glob->framerate = *fps; write_webm_seek_info(glob); /* Open and write the Tracks element. */ glob->track_pos = ftello(glob->stream); Ebml_StartSubElement(glob, &trackStart, Tracks); /* Open and write the Track entry. */ Ebml_StartSubElement(glob, &start, TrackEntry); Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); glob->track_id_pos = ftello(glob->stream); Ebml_SerializeUnsigned32(glob, TrackUID, trackID); Ebml_SerializeUnsigned(glob, TrackType, 1); Ebml_SerializeString(glob, CodecID, fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9"); Ebml_StartSubElement(glob, &videoStart, Video); Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt); Ebml_EndSubElement(glob, &videoStart); /* Close Track entry. */ Ebml_EndSubElement(glob, &start); /* Close Tracks element. */ Ebml_EndSubElement(glob, &trackStart); /* Segment element remains open. */
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} void write_webm_block(struct EbmlGlobal *glob, const vpx_codec_enc_cfg_t *cfg, const vpx_codec_cx_pkt_t *pkt) { unsigned int block_length; unsigned char track_number; uint16_t block_timecode = 0; unsigned char flags; int64_t pts_ms; int start_cluster = 0, is_keyframe; /* Calculate the PTS of this frame in milliseconds. */ pts_ms = pkt->data.frame.pts * 1000 * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den; if (pts_ms <= glob->last_pts_ms) pts_ms = glob->last_pts_ms + 1; glob->last_pts_ms = pts_ms; /* Calculate the relative time of this block. */ if (pts_ms - glob->cluster_timecode > SHRT_MAX) start_cluster = 1; else block_timecode = (uint16_t)pts_ms - glob->cluster_timecode; is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY); if (start_cluster || is_keyframe) { if (glob->cluster_open) Ebml_EndSubElement(glob, &glob->startCluster); /* Open the new cluster. */ block_timecode = 0; glob->cluster_open = 1; glob->cluster_timecode = (uint32_t)pts_ms; glob->cluster_pos = ftello(glob->stream); Ebml_StartSubElement(glob, &glob->startCluster, Cluster); Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode); /* Save a cue point if this is a keyframe. */ if (is_keyframe) { struct cue_entry *cue, *new_cue_list; new_cue_list = realloc(glob->cue_list, (glob->cues + 1) * sizeof(struct cue_entry)); if (new_cue_list) glob->cue_list = new_cue_list; else fatal("Failed to realloc cue list."); cue = &glob->cue_list[glob->cues]; cue->time = glob->cluster_timecode; cue->loc = glob->cluster_pos; glob->cues++; } } /* Write the Simple Block. */ Ebml_WriteID(glob, SimpleBlock); block_length = (unsigned int)pkt->data.frame.sz + 4; block_length |= 0x10000000; Ebml_Serialize(glob, &block_length, sizeof(block_length), 4); track_number = 1; track_number |= 0x80; Ebml_Write(glob, &track_number, 1); Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
flags = 0; if (is_keyframe) flags |= 0x80; if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) flags |= 0x08; Ebml_Write(glob, &flags, 1); Ebml_Write(glob, pkt->data.frame.buf, (unsigned int)pkt->data.frame.sz); } void write_webm_file_footer(struct EbmlGlobal *glob, int hash) { EbmlLoc start_cues; EbmlLoc start_cue_point; EbmlLoc start_cue_tracks; unsigned int i; if (glob->cluster_open) Ebml_EndSubElement(glob, &glob->startCluster); glob->cue_pos = ftello(glob->stream); Ebml_StartSubElement(glob, &start_cues, Cues); for (i = 0; i < glob->cues; i++) { struct cue_entry *cue = &glob->cue_list[i]; Ebml_StartSubElement(glob, &start_cue_point, CuePoint); Ebml_SerializeUnsigned(glob, CueTime, cue->time); Ebml_StartSubElement(glob, &start_cue_tracks, CueTrackPositions); Ebml_SerializeUnsigned(glob, CueTrack, 1); Ebml_SerializeUnsigned64(glob, CueClusterPosition, cue->loc - glob->position_reference); Ebml_EndSubElement(glob, &start_cue_tracks); Ebml_EndSubElement(glob, &start_cue_point); } Ebml_EndSubElement(glob, &start_cues); /* Close the Segment. */ Ebml_EndSubElement(glob, &glob->startSegment); /* Patch up the seek info block. */ write_webm_seek_info(glob); /* Patch up the track id. */ fseeko(glob->stream, glob->track_id_pos, SEEK_SET); Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash); fseeko(glob->stream, 0, SEEK_END); }